home *** CD-ROM | disk | FTP | other *** search
/ CD Ware Multimedia 1998 May / CD Ware 43.iso / Monogra / Prg / source.exe / LPARSER.C < prev   
Encoding:
C/C++ Source or Header  |  1997-03-17  |  98.5 KB  |  3,175 lines

  1. /* -------------------------------------------------------------------------
  2.    LPARSER, L-System Parser/Mutator
  3.    -------------------------------------------------------------------------
  4.    Laurens Lapre
  5.    ljlapre@xs4all.nl
  6.    http://www.xs4all.nl/~ljlapre/
  7.    -------------------------------------------------------------------------
  8. */
  9.  
  10.  
  11. /* Includes --------------------------------------------------------------- */
  12.  
  13.  
  14. #include <stdio.h>
  15. #include <float.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <stdarg.h>
  19. #include <math.h>
  20. #include <malloc.h>
  21.  
  22.  
  23. /* Basic types ------------------------------------------------------------ */
  24.  
  25.  
  26. /* Simple types */
  27. #define u8               unsigned char
  28. #define u16              unsigned short int
  29. #define u32              unsigned long int
  30. #define s8               signed char
  31. #define s16              signed short int
  32. #define s32              signed long int
  33. #define r32              float
  34. #define r64              double
  35.  
  36. /* My own boolean type */
  37. #define boolean          s16
  38. #ifndef TRUE
  39. #define TRUE             (s16) 1
  40. #endif
  41. #ifndef FALSE
  42. #define FALSE            (s16) 0
  43. #endif
  44.  
  45.  
  46. /* Constants -------------------------------------------------------------- */
  47.  
  48.  
  49. /* Max char size of filename and large string */
  50. #define max_file         512
  51.  
  52. /* Max vectors per polygon */
  53. #define vectors_p_poly   15
  54.  
  55. /* Max polygons per object */
  56. #define max_p_object     400
  57.  
  58. /* Max size of the [] and {} stacks during drawing */
  59. #define max_stack        1024L
  60.  
  61. /* Max number of the rules in the ls file */
  62. #define rule_n           200
  63.  
  64. /* Max size of the rules in the ls file */
  65. #define rule_s           500
  66.  
  67. /* Version id for the VOL file format */
  68. #define VersionID        11
  69.  
  70. /* Vector indices */
  71. #define _x               0
  72. #define _y               1
  73. #define _z               2
  74.  
  75. /* Some often used consts */
  76. #define zero             (r32) 0.0
  77. #define one              (r32) 1.0
  78. #define half_pi          (r32) 1.570796
  79. #define pi               (r32) 3.141592
  80. #define two_pi           (r32) 6.283185
  81. #define LF               ((char) 10)
  82. #define CR               ((char) 13)
  83. #define min_bar          "---------------------------------------------------------"
  84.  
  85. /* Bounding space for floats */
  86. #define float_min        (r32) -1e30
  87. #define float_max        (r32)  1e30
  88.  
  89.  
  90. /* Array and vector types ------------------------------------------------- */
  91.  
  92.  
  93. /* A large string */
  94. typedef char            string_file[max_file];
  95.  
  96. /* Vector arrays */
  97. typedef r32             vector[3];
  98. typedef vector          vectors_4[4];
  99. typedef vector          vectors_max[vectors_p_poly];
  100. typedef r32             float_array[max_p_object + 1];
  101.  
  102. /* Polygon arrays */
  103. typedef s16             polygon_type[4];
  104. typedef polygon_type    polygon_array[max_p_object + 1];
  105.  
  106.  
  107. /* Intrinsics ------------------------------------------------------------- */
  108.  
  109.  
  110. #define Abs_s16(A)       ((s16) abs((A)))
  111. #define Abs_s32(A)       ((s32) abs((A)))
  112. #define Abs_r32(A)       ((r32) fabs((A)))
  113. #define Abs_r64(A)       ((r64) fabs((A)))
  114.  
  115. #define MIN(A,B)         (((A) < (B)) ? (A) : (B))
  116. #define MAX(A,B)         (((A) > (B)) ? (A) : (B))
  117.  
  118. #define Vector_copy_max_r32(n,A,B) memcpy(((void *) (B)), ((void *) (A)), n*12L)
  119. #define Vector_copy_r32(A,B)       memcpy(((void *) (B)), ((void *) (A)),   12L)
  120. #define Mem_copy(A,B,C)            memcpy(((void *) (B)), ((void *) (A)), (C))
  121. #define Mem_clear(A,B,C)           memset(((void *) (A)), (C), (B))
  122.  
  123.  
  124. /* Vector utils and inlines ----------------------------------------------- */
  125.  
  126.  
  127. #define Clip_low(a,b)   a = ((a) < (b)) ? (b) : (a)
  128. #define Clip_high(a,b)  a = ((a) > (b)) ? (b) : (a)
  129. #define Clamp(a,b,c)    a = ((a) < (b)) ? (b) : ((a) > (c)) ? (c) : (a)
  130. #define Wrap(a,b,c)     a = ((a) < (b)) ? (a) + (c) : ((a) > (c)) ? (a) - (c) : (a)
  131. #define Lerp(a,b,c)     ((b) + (((c) - (b)) * (a)))
  132. #define Swap(a,b)       {(a) ^= (b); (b) ^= (a); (a) ^= (b);}
  133.  
  134. #define Vector_length(A)    ((r32) sqrt(   (r32)(A[_x] * A[_x])\
  135.                                          + (r32)(A[_y] * A[_y])\
  136.                                          + (r32)(A[_z] * A[_z]) ))
  137.  
  138. #define Vector_equal(A,B)   ((A[_x] == B[_x]) && (A[_y] == B[_y]) && (A[_z] == B[_z]))
  139. #define Scalar_product(A,B) (A[_x] * B[_x] + A[_y] * B[_y] + A[_z] * B[_z])
  140.  
  141. #define Vector_make(A,a,b,c) {\
  142.   A[_x] = a;\
  143.   A[_y] = b;\
  144.   A[_z] = c;\
  145. }
  146.  
  147. #define Vector_break(A,a,b,c) {\
  148.   a = A[_x];\
  149.   b = A[_y];\
  150.   c = A[_z];\
  151. }
  152.  
  153. #define Vector_lerp(a,A,B) {\
  154.   A[_x] = Lerp(a, A[_x], B[_x]);\
  155.   A[_y] = Lerp(a, A[_y], B[_y]);\
  156.   A[_z] = Lerp(a, A[_z], B[_z]);\
  157. }
  158.  
  159. #define Vector_normalize(A)\
  160. { r32 Dist = (r32) 1.0 / Vector_length(A);\
  161. \
  162.   A[_x] *= Dist;\
  163.   A[_y] *= Dist;\
  164.   A[_z] *= Dist;\
  165. }
  166.  
  167. #define Vector_copy(A,B) {\
  168.   B[_x] = A[_x];\
  169.   B[_y] = A[_y];\
  170.   B[_z] = A[_z];\
  171. }
  172.  
  173. #define Vector_product(A,B,C) {\
  174.   C[_x] = A[_y] * B[_z] - A[_z] * B[_y];\
  175.   C[_y] = A[_z] * B[_x] - A[_x] * B[_z];\
  176.   C[_z] = A[_x] * B[_y] - A[_y] * B[_x];\
  177. }
  178.  
  179. #define Vector_min(A,B,C) {\
  180.   C[_x] = A[_x] - B[_x];\
  181.   C[_y] = A[_y] - B[_y];\
  182.   C[_z] = A[_z] - B[_z];\
  183. }
  184.  
  185. #define Vector_plus(A,B,C) {\
  186.   C[_x] = A[_x] + B[_x];\
  187.   C[_y] = A[_y] + B[_y];\
  188.   C[_z] = A[_z] + B[_z];\
  189. }
  190.  
  191. #define Vector_dec(A,B) {\
  192.   A[_x] -= B[_x];\
  193.   A[_y] -= B[_y];\
  194.   A[_z] -= B[_z];\
  195. }
  196.  
  197. #define Vector_neg(A) {\
  198.   A[_x] = (-A[_x]);\
  199.   A[_y] = (-A[_y]);\
  200.   A[_z] = (-A[_z]);\
  201. }
  202.  
  203. #define Vector_inc(A,B) {\
  204.   A[_x] += B[_x];\
  205.   A[_y] += B[_y];\
  206.   A[_z] += B[_z];\
  207. }
  208.  
  209. #define Vector_plus_fac(A,B,t,C) {\
  210.   C[_x] = A[_x] + (t) * B[_x];\
  211.   C[_y] = A[_y] + (t) * B[_y];\
  212.   C[_z] = A[_z] + (t) * B[_z];\
  213. }
  214.  
  215. #define Vector_plus_fac2(A,B,b,C,c,D) {\
  216.   D[_x] = A[_x] + (b) * B[_x] + (c) * C[_x];\
  217.   D[_y] = A[_y] + (b) * B[_y] + (c) * C[_y];\
  218.   D[_z] = A[_z] + (b) * B[_z] + (c) * C[_z];\
  219. }
  220.  
  221. #define Vector_combine(A,a,B,b,C) {\
  222.   C[_x] = (a) * A[_x] + (b) * B[_x];\
  223.   C[_y] = (a) * A[_y] + (b) * B[_y];\
  224.   C[_z] = (a) * A[_z] + (b) * B[_z];\
  225. }
  226.  
  227. #define Vector_add(A,d) {\
  228.   A[_x] += d;\
  229.   A[_y] += d;\
  230.   A[_z] += d;\
  231. }
  232.  
  233. #define Vector_sub(A,d) {\
  234.   A[_x] -= d;\
  235.   A[_y] -= d;\
  236.   A[_z] -= d;\
  237. }
  238.  
  239. #define Vector_div(A,d) {\
  240.   A[_x] /= d;\
  241.   A[_y] /= d;\
  242.   A[_z] /= d;\
  243. }
  244.  
  245. #define Vector_mul(A,d) {\
  246.   A[_x] *= d;\
  247.   A[_y] *= d;\
  248.   A[_z] *= d;\
  249. }
  250.  
  251.  
  252. /* Vector procs ----------------------------------------------------------- */
  253.  
  254.  
  255. static vector           M1, M2, M3;         /* The current movetransform matrix */
  256.  
  257.  
  258. r32
  259. Do_angle(r32 x1, r32 y1, r32 x2, r32 y2)
  260. {                                           /* Calculate the angle between
  261.                                              * x-axis and x1,y1 -> x2,y2. It
  262.                                              * can handle all kinds of weird
  263.                                              * exceptions */
  264.     r32                     temp, x, y;
  265.  
  266.     x = x2 - x1;
  267.     y = y2 - y1;
  268.  
  269.     if (x == zero) {
  270.         if (y < zero)
  271.             temp = -half_pi;
  272.         else
  273.             temp = half_pi;
  274.     } else {
  275.         temp = atan(y / x);
  276.         if (x < zero) {
  277.             if (y < zero)
  278.                 temp = -pi + temp;
  279.             else
  280.                 temp = pi + temp;
  281.         }
  282.     }
  283.  
  284.     if (Abs_r32(temp) < (r32) 0.0001)
  285.         temp = zero;
  286.  
  287.     if (temp < zero)
  288.         temp += two_pi;
  289.     else if (temp > two_pi)
  290.         temp -= two_pi;
  291.  
  292.     return temp;
  293. }
  294.  
  295.  
  296. void
  297. Move_transform(vector v)
  298. {                                           /* Transform the vector according
  299.                                              * to the current movetransform
  300.                                              * matrix */
  301.     vector                  t;
  302.  
  303.     Vector_copy_r32(v, t);
  304.     v[_x] = Scalar_product(M1, t);
  305.     v[_y] = Scalar_product(M2, t);
  306.     v[_z] = Scalar_product(M3, t);
  307. }
  308.  
  309.  
  310. void
  311. Set_move_transform(r32 a, vector no)
  312. {                                           /* Set a movetransformation matrix
  313.                                              * based on an angle rotation of
  314.                                              * 'a' around the vector 'no' */
  315.     r32                     n11, n22, n33, nxy, nxz, nyz, sina, cosa;
  316.  
  317.     cosa = (r32) cos(a);
  318.     sina = (r32) sin(a);
  319.  
  320.     n11 = no[_x] * no[_x];
  321.     n22 = no[_y] * no[_y];
  322.     n33 = no[_z] * no[_z];
  323.  
  324.     nxy = no[_x] * no[_y];
  325.     nxz = no[_x] * no[_z];
  326.     nyz = no[_y] * no[_z];
  327.  
  328.     M1[_x] = n11 + (one - n11) * cosa;
  329.     M1[_y] = nxy * (one - cosa) - no[_z] * sina;
  330.     M1[_z] = nxz * (one - cosa) + no[_y] * sina;
  331.  
  332.     M2[_x] = nxy * (one - cosa) + no[_z] * sina;
  333.     M2[_y] = n22 + (one - n22) * cosa;
  334.     M2[_z] = nyz * (one - cosa) - no[_x] * sina;
  335.  
  336.     M3[_x] = nxz * (one - cosa) - no[_y] * sina;
  337.     M3[_y] = nyz * (one - cosa) + no[_x] * sina;
  338.     M3[_z] = n33 + (one - n33) * cosa;
  339. }
  340.  
  341.  
  342. /* File and conio procs --------------------------------------------------- */
  343.  
  344.  
  345. static boolean          native_mode = TRUE;
  346.  
  347.  
  348. void
  349. Set_lowhigh(boolean b)
  350. {                                           /* TRUE native Intel mode Low-High,
  351.                                              * FALSE High-Low */
  352.     native_mode = b;
  353. }
  354.  
  355.  
  356. void
  357. User_error(char *s,...)
  358. {                                           /* Displays and error messages and
  359.                                              * exits the program */
  360.     string_file             buf;
  361.     va_list                 args;
  362.  
  363.     va_start(args, s);
  364.     vsprintf(buf, s, args);
  365.     va_end(args);
  366.  
  367.     fprintf(stdout, "\n\nError: %s\n\n", buf);
  368.     fflush(stdout);
  369.  
  370.     exit(EXIT_FAILURE);
  371. }
  372.  
  373.  
  374. void
  375. Message(char *s,...)
  376. {                                           /* Sends a message to the output
  377.                                              * stream */
  378.     string_file             buf;
  379.     va_list                 args;
  380.  
  381.     va_start(args, s);
  382.     vsprintf(buf, s, args);
  383.     va_end(args);
  384.  
  385.     fprintf(stdout, "%s", buf);
  386.     fflush(stdout);
  387.     fflush(stdout);
  388. }
  389.  
  390.  
  391. void
  392. Fget_string(FILE * f, char *s)
  393. {                                           /* Get a string from a file. Used
  394.                                              * for parsing the LS files */
  395.     s16                     i = 0;
  396.     char                    c;
  397.  
  398.     s[0] = '\0';
  399.     for (;;) {
  400.         c = (char) getc(f);
  401.         if (feof(f))
  402.             return;
  403.         if (c == '\r')
  404.             continue;
  405.         if (c == LF)
  406.             break;
  407.         s[i++] = c;
  408.     }
  409.     s[i] = '\0';
  410. }
  411.  
  412.  
  413. void
  414. Fget_bin_r32(FILE * f, r32 *val)
  415. {                                           /* Get a r32 value, check for order */
  416.     s32                     temp, ta, tb, tc, td;
  417.     r32                    *tempr = ((r32 *) ((void *) &temp));
  418.  
  419.     ta = (s32) getc(f);
  420.     tb = (s32) getc(f);
  421.     tc = (s32) getc(f);
  422.     td = (s32) getc(f);
  423.  
  424.     if (native_mode) {
  425.         temp = td << 8;
  426.         temp += tc;
  427.         temp = temp << 8;
  428.         temp += tb;
  429.         temp = temp << 8;
  430.         temp += ta;
  431.     } else {
  432.         temp = ta << 8;
  433.         temp += tb;
  434.         temp = temp << 8;
  435.         temp += tc;
  436.         temp = temp << 8;
  437.         temp += td;
  438.     }
  439.  
  440.     *val = *tempr;
  441. }
  442.  
  443.  
  444. void
  445. Fget_bin_s16(FILE * f, s16 *val)
  446. {                                           /* Get a s16 value, check for order */
  447.     s32                     ta, tb;
  448.  
  449.     ta = (s32) getc(f);
  450.     tb = (s32) getc(f);
  451.  
  452.     if (native_mode) {
  453.         *val = (s16) tb << 8;
  454.         *val += (s16) ta;
  455.     } else {
  456.         *val = (s16) ta << 8;
  457.         *val += (s16) tb;
  458.     }
  459. }
  460.  
  461.  
  462. void
  463. Fget_bin_s32(FILE * f, s32 *val)
  464. {                                           /* Get a s32 value, check for order */
  465.     s32                     ta, tb, tc, td;
  466.  
  467.     ta = (s32) getc(f);
  468.     tb = (s32) getc(f);
  469.     tc = (s32) getc(f);
  470.     td = (s32) getc(f);
  471.  
  472.     if (native_mode) {
  473.         *val = td << 8;
  474.         *val += tc;
  475.         *val = *val << 8;
  476.         *val += tb;
  477.         *val = *val << 8;
  478.         *val += ta;
  479.     } else {
  480.         *val = ta << 8;
  481.         *val += tb;
  482.         *val = *val << 8;
  483.         *val += tc;
  484.         *val = *val << 8;
  485.         *val += td;
  486.     }
  487. }
  488.  
  489.  
  490. void
  491. Fget_bin_u16(FILE * f, u16 *val)
  492. {                                           /* Get a u16 value, check for order */
  493.     s32                     ta, tb;
  494.  
  495.     ta = (s32) getc(f);
  496.     tb = (s32) getc(f);
  497.  
  498.     if (native_mode) {
  499.         *val = (u16) tb << 8;
  500.         *val += (u16) ta;
  501.     } else {
  502.         *val = (u16) ta << 8;
  503.         *val += (u16) tb;
  504.     }
  505.  
  506. }
  507.  
  508.  
  509. void
  510. Fget_bin_s8(FILE * f, s8 *val)
  511. {
  512.     *val = (s8) getc(f);
  513. }
  514.  
  515.  
  516. void
  517. Fget_bin_u8(FILE * f, u8 *val)
  518. {
  519.     *val = (u8) getc(f);
  520. }
  521.  
  522.  
  523. void
  524. Fget_bin_u32(FILE * f, u32 *val)
  525. {                                           /* Get a u32 value, check for order */
  526.     s32                     ta, tb, tc, td;
  527.  
  528.     ta = (s32) getc(f);
  529.     tb = (s32) getc(f);
  530.     tc = (s32) getc(f);
  531.     td = (s32) getc(f);
  532.  
  533.     if (native_mode) {
  534.         *val = td << 8;
  535.         *val += tc;
  536.         *val = *val << 8;
  537.         *val += tb;
  538.         *val = *val << 8;
  539.         *val += ta;
  540.     } else {
  541.         *val = ta << 8;
  542.         *val += tb;
  543.         *val = *val << 8;
  544.         *val += tc;
  545.         *val = *val << 8;
  546.         *val += td;
  547.     }
  548. }
  549.  
  550.  
  551. void
  552. Fput_bin_u8(FILE * f, u8 r)
  553. {
  554.     if (fwrite(&r, sizeof(u8), 1, f) != 1)
  555.         User_error("Can't continue writing outputfile");
  556. }
  557.  
  558.  
  559. void
  560. Fput_bin_s8(FILE * f, s8 r)
  561. {
  562.     if (fwrite(&r, sizeof(s8), 1, f) != 1)
  563.         User_error("Can't continue writing outputfile");
  564. }
  565.  
  566.  
  567. void
  568. Fput_bin_r32(FILE * f, r32 r)
  569. {
  570.     if (fwrite(&r, sizeof(r32), 1, f) != 1)
  571.         User_error("Can't continue writing outputfile");
  572. }
  573.  
  574.  
  575. void
  576. Fput_bin_s16(FILE * f, s16 r)
  577. {
  578.     if (fwrite(&r, sizeof(s16), 1, f) != 1)
  579.         User_error("Can't continue writing outputfile");
  580. }
  581.  
  582.  
  583. void
  584. Fput_bin_u16(FILE * f, u16 r)
  585. {
  586.     if (fwrite(&r, sizeof(u16), 1, f) != 1)
  587.         User_error("Can't continue writing outputfile");
  588. }
  589.  
  590.  
  591. void
  592. Fput_bin_s32(FILE * f, s32 r)
  593. {
  594.     if (fwrite(&r, sizeof(s32), 1, f) != 1)
  595.         User_error("Can't continue writing outputfile");
  596. }
  597.  
  598.  
  599. void
  600. Fput_bin_u32(FILE * f, u32 r)
  601. {
  602.     if (fwrite(&r, sizeof(u32), 1, f) != 1)
  603.         User_error("Can't continue writing outputfile");
  604. }
  605.  
  606.  
  607. /* File buffer procs ------------------------------------------------------ */
  608.  
  609.  
  610. /* Sinces there is a lot of fileio we use large buffers */
  611. #define f_buffer_size  30L * 1024L
  612. static char            *f_buffer[3] = {NULL, NULL, NULL};
  613.  
  614.  
  615. void
  616. Buffer_IO(FILE * f, s16 i)
  617. {                                           /* Attach filebuffer i to open file */
  618.     setvbuf(f, f_buffer[i], _IOFBF, f_buffer_size);
  619. }
  620.  
  621.  
  622. void
  623. Init_file_buf(s16 i)
  624. {                                           /* Init filebuffer i */
  625.     if (f_buffer[i] != NULL)
  626.         return;
  627.     f_buffer[i] = (char *) malloc(f_buffer_size);
  628.     if (f_buffer[i] == NULL)
  629.         User_error("Not enough memory to allocate file buffer");
  630. }
  631.  
  632.  
  633. /* Feedback percentage counter -------------------------------------------- */
  634.  
  635.  
  636. /* These vars are used to calculate the percentages counters for feedback */
  637. static r32              bar_fac2 = zero;
  638. static s16              old_bar2 = 0;
  639. static u32              bar_max2 = 0;
  640.  
  641.  
  642. void
  643. Process_start2(u32 max)
  644. {                                           /* Start bar 2 with the maximum
  645.                                              * value it's going to get */
  646.     bar_fac2 = 100.0 / (r32) max;
  647.     bar_max2 = max;
  648. }
  649.  
  650.  
  651. void
  652. Process_update2(u32 now)
  653. {                                           /* Update the percentage counter
  654.                                              * when needed */
  655.     s16                     bar = (s16) (bar_fac2 * (r32) now);
  656.  
  657.     if (bar != old_bar2) {
  658.         old_bar2 = bar;
  659.         Message("\r%3d%%\r", bar);
  660.     }
  661. }
  662.  
  663.  
  664. void
  665. Process_end2(void)
  666. {                                           /* Close bar */
  667.     Message("\r    \r");
  668. }
  669.  
  670.  
  671. /* Comline procs ---------------------------------------------------------- */
  672.  
  673.  
  674. #define OPTCHAR '-'
  675.  
  676. static char             empty[] = "";
  677. static char            *optarg = empty;
  678. static int              optind = 1, opterr = 1;
  679. static char             opts[150] = "";     /* option string */
  680. static s16              s_argc = 0;         /* pointers to comline */
  681. static char           **s_argv = NULL;
  682.  
  683.  
  684. static int
  685. getopt(int argc, char *argv[], const char *optstring)
  686. {                                           /* Taken from a source lib
  687.                                              * somewhere */
  688.     static char            *in_pointer = empty;
  689.     char                   *find;
  690.  
  691.     if (!*in_pointer) {
  692.         if ((!argv[optind]) || (optind >= argc) || (argv[optind][0] != OPTCHAR))
  693.             return -1;
  694.         in_pointer = argv[optind];
  695.         in_pointer++;
  696.         optind++;
  697.         if (*in_pointer == OPTCHAR) {
  698.             return -1;
  699.         }
  700.     };
  701.  
  702.     if (*in_pointer == '\0') {
  703.         return 0;
  704.     };
  705.  
  706.     find = strchr(optstring, *in_pointer);
  707.     if (find == NULL) {
  708.         if (opterr)
  709.             User_error("Option -%c not known", *in_pointer);
  710.         in_pointer = empty;
  711.         return '?';
  712.     };
  713.  
  714.     if (*(find + 1) == ':') {
  715.         if (!*(in_pointer + 1)) {
  716.             if (optind >= argc) {
  717.                 if (opterr)
  718.                     User_error("No argument for option -%c", *in_pointer);
  719.                 optarg = empty;
  720.             } else {
  721.                 if (argv[optind][0] == OPTCHAR) {
  722.                     if (opterr)
  723.                         User_error("No argument for option -%c but found %s instead", *in_pointer, argv[optind]);
  724.                 }
  725.                 optarg = argv[optind++];
  726.             }
  727.         } else {
  728.             optarg = ++in_pointer;
  729.         }
  730.         in_pointer = empty;
  731.     } else {
  732.         optarg = empty;
  733.         in_pointer++;
  734.     }
  735.  
  736.     return *find;
  737. }
  738.  
  739.  
  740. void
  741. Get_comline_opt(char *c, boolean * found, char *result)
  742. {                                           /* Check if comline option 'c' has
  743.                                              * been used and return parameter
  744.                                              * if any */
  745.     int                     f, argc;
  746.     char                  **argv;
  747.  
  748.     argc = s_argc;
  749.     argv = s_argv;
  750.     optind = 1;
  751.  
  752.     while ((f = getopt(argc, argv, opts)) != -1) {
  753.  
  754.         if (f == *c) {
  755.             strcpy(result, optarg);
  756.             *found = TRUE;
  757.             return;
  758.         }
  759.     };
  760.  
  761.     *found = FALSE;
  762.     strcpy(result, "");
  763. }
  764.  
  765.  
  766. void
  767. Get_comline_filename(char *c)
  768. {                                           /* Get the filename argument from
  769.                                              * the comline */
  770.     int                     argc;
  771.     char                  **argv;
  772.  
  773.     argc = s_argc;
  774.     argv = s_argv;
  775.     optind = 1;
  776.  
  777.     while (getopt(argc, argv, opts) != -1);
  778.  
  779.     if (optind == argc)
  780.         User_error("Ran out of arguments before finding file name");
  781.  
  782.     strcpy(c, argv[optind]);
  783. }
  784.  
  785.  
  786. void
  787. Get_comline_progname(char *c)
  788. {                                           /* Get the program name from the
  789.                                              * comline */
  790.     strcpy(c, s_argv[0]);
  791. }
  792.  
  793.  
  794. /* Main lparser vars ------------------------------------------------------ */
  795.  
  796.  
  797. /* Settings stack used for solving [] references */
  798. typedef struct s_rec {
  799.     vector                  pos;            /* position in 3space of turtle
  800.                                              * origin */
  801.     vector                  fow;            /* forward direction */
  802.  
  803.     vector                  lef;            /* left direction */
  804.     vector                  upp;            /* up direction */
  805.     vector                  last;           /* last position used for
  806.                                              * connecting cylinders */
  807.     vector                  last_v[9];      /* last vertices of object used for
  808.                                              * connecting cylinders */
  809.     r32                     dis;            /* value of F distance */
  810.     r32                     ang;            /* value of basic angle */
  811.     r32                     thick;          /* value of thickness */
  812.     r32                     dis2;           /* value of Z distance */
  813.     r32                     tr;             /* trope value */
  814.     s16                     col;            /* current color */
  815.     s16                     last_col;       /* color of last object */
  816. } s_rec;
  817.  
  818. /* Polygon stack used for solving {} references */
  819. typedef struct p_rec {
  820.     s16                     count;          /* number of vertices */
  821.     vector                 *ver;            /* vertex store */
  822. } p_rec;
  823.  
  824. /* Flags */
  825. static boolean          trope_set = FALSE;  /* see at comline scannign */
  826. static boolean          rand_set = FALSE;
  827. static boolean          user_form = FALSE;
  828. static boolean          closed_form = FALSE;
  829. static boolean          pov_form = FALSE;
  830. static boolean          pov_form2 = FALSE;
  831. static boolean          pov_form3 = FALSE;
  832. static boolean          blb_form = FALSE;
  833. static boolean          inc_out = FALSE;
  834. static boolean          dxf1 = FALSE;
  835. static boolean          dxf2 = FALSE;
  836. static boolean          dxf3 = FALSE;
  837. static boolean          vrml = FALSE;
  838. static boolean          growing = FALSE;    /* real is used for recursion level */
  839. static boolean          last_recur = FALSE; /* processing the last recursion
  840.                                              * step */
  841.  
  842. /* Rule and strings storage */
  843. static char             rule[rule_n][rule_s];   /* the rule store */
  844. static char            *object_s, *otemp;   /* the two strings used for
  845.                                              * building the production string */
  846. static s16              size[rule_n];       /* size of the rule in the rule
  847.                                              * store */
  848. static boolean          mark[rule_n];       /* marked rules need special
  849.                                              * processing when growing shapes
  850.                                              * are active */
  851.  
  852. /* Init vars */
  853. static r32              zmin = 1e30, thick, min_thick = zero, rand_amount = zero;
  854. static r32              trope_amount = zero;
  855. static u32              polcount = 0;
  856. static u32              poly_limit = 500000L, max_string;
  857. static s16              num = 0, col = 2, lev, last_col = 0;
  858. static r32              dis, ang, dis2, tr = 0.2;
  859. static vector           sky = {0.0, 0.0, 1.0}, trope;
  860. static vector           last = {1.0, 1.0, 1.0}, last_v[9];
  861. static r32              recursion, fraction;
  862. static vector           axis_x, axis_y, axis_z;
  863.  
  864. /* Stacks [] and {} */
  865. static s_rec           *stack, org, save;
  866. static s16              scount = 0;
  867. static p_rec           *pstack;
  868. static s16              pscount = 0;
  869.  
  870. /* Current active transform matrix for drawing */
  871. static vector           C1, C2, C3;
  872.  
  873. /* Var for rnd */
  874. static r32              rm = (r32) 1.0 / (r32) RAND_MAX;
  875.  
  876. /* Ouput files */
  877. static FILE            *volume_file = NULL; /* the basic open geometry file */
  878. static FILE            *vf[8];              /* the 8 files when writing
  879.                                              * multiple povray blob files */
  880.  
  881. /* Object stores */
  882. static polygon_array    poly_store;         /* the store where polygons
  883.                                              * accumulate before saved to disc */
  884. static vector           ver[max_p_object];  /* the store where vertices
  885.                                              * accumulate */
  886.  
  887. /* Storage of a loaded shape for the -X option */
  888. static char             x_name[max_file];   /* filename of VOL file */
  889. static vector           form_c[max_p_object];   /* vertices */
  890. static polygon_array    form_s;             /* polygons */
  891. static s16              form_ver, form_pol; /* vertices and polygon counts */
  892.  
  893.  
  894. /* Check for weird polygons ----------------------------------------------- */
  895.  
  896.  
  897.  /*
  898.   * Sometimes polygons and/or vertices end up containing floating pint
  899.   * exception like NAN etc. These routines find these problems. They can create
  900.   * havoc on input parsers which expect the geometry to be flawless. Typical,
  901.   * normalization routines blow up on NAN in vectors.
  902.   */
  903.  
  904.  
  905. /* IEEE coded floating point exceptions */
  906. static u32              fp_exp1 = 0x7f800000L;
  907. static u32              fp_exp2 = 0xff800000L;
  908. static u32              fp_exp3 = 0xffc00000L;
  909. static u32              fp_exp4 = 0x7fc00000L;
  910.  
  911.  
  912. static                  boolean
  913. Bad_vertex(r32 x, r32 y, r32 z)
  914. {                                           /* Does this vertex contain a
  915.                                              * floation point exception ? */
  916.     union {
  917.         r32                     f;
  918.         u32                     i;
  919.     }                       u;
  920.  
  921.     u.f = x;
  922.     if ((u.i == fp_exp1) ||
  923.             (u.i == fp_exp2) ||
  924.             (u.i == fp_exp3) ||
  925.             (u.i == fp_exp4)) {
  926.         return TRUE;
  927.     };
  928.  
  929.     u.f = y;
  930.     if ((u.i == fp_exp1) ||
  931.             (u.i == fp_exp2) ||
  932.             (u.i == fp_exp3) ||
  933.             (u.i == fp_exp4)) {
  934.         return TRUE;
  935.     };
  936.  
  937.     u.f = z;
  938.     if ((u.i == fp_exp1) ||
  939.             (u.i == fp_exp2) ||
  940.             (u.i == fp_exp3) ||
  941.             (u.i == fp_exp4)) {
  942.         return TRUE;
  943.     };
  944.  
  945.     return FALSE;
  946. }
  947.  
  948.  
  949. static                  boolean
  950. Invalid_polygon(s16 p)
  951. {                                           /* Can a normal be created on this
  952.                                              * polygon ? */
  953.     vector                  X, Y, Z, N;
  954.     s16                     i;
  955.     r32                     D, x, y, z;
  956.  
  957.     for (i = 0; i < 4; i++) {
  958.         x = ver[poly_store[p][i]][_x];
  959.         y = ver[poly_store[p][i]][_y];
  960.         z = ver[poly_store[p][i]][_z];
  961.         if (Bad_vertex(x, y, z))
  962.             return TRUE;
  963.     }
  964.  
  965.     for (i = 0; i < 3; i++) {
  966.         X[i] = ver[poly_store[p][i]][_x];
  967.         Y[i] = ver[poly_store[p][i]][_y];
  968.         Z[i] = ver[poly_store[p][i]][_z];
  969.     }
  970.  
  971.     N[_x] = Y[_x] * (Z[_y] - Z[_z]) + Y[_y] * (Z[_z] - Z[_x]) + Y[_z] * (Z[_x] - Z[_y]);
  972.     N[_y] = ((-X[_x])) * (Z[_y] - Z[_z]) - X[_y] * (Z[_z] - Z[_x]) - X[_z] * (Z[_x] - Z[_y]);
  973.     N[_z] = X[_x] * (Y[_y] - Y[_z]) + X[_y] * (Y[_z] - Y[_x]) + X[_z] * (Y[_x] - Y[_y]);
  974.  
  975.     D = N[_x] * N[_x] + N[_y] * N[_y] + N[_z] * N[_z];
  976.  
  977.     if (D <= (r32) 0.0001)
  978.         return TRUE;
  979.     else
  980.         return FALSE;
  981. }
  982.  
  983.  
  984. /* Output data file procs ------------------------------------------------- */
  985.  
  986.  
  987. static void
  988. Open_datafile(void)
  989. {                                           /* Open and setup the different
  990.                                              * output files depending on the
  991.                                              * flags */
  992.  
  993.     char                    S[max_file] = "";
  994.     s16                     i;
  995.  
  996.     if (pov_form || pov_form2) {
  997.         strcpy(S, inc_out ? "output.inc" : "output.pov");
  998.         Message("Pov file       : %s\n", S);
  999.         volume_file = fopen(S, "wt");
  1000.         if (!volume_file)
  1001.             User_error("Cannot open file [%s]", S);
  1002.         Buffer_IO(volume_file, 0);
  1003.         return;
  1004.  
  1005.     } else if (pov_form3) {
  1006.         for (i = 0; i < 8; i++) {
  1007.             sprintf(S, inc_out ? "output%d.inc" : "output%d.pov", i);
  1008.             Message("Pov file       : %s\n", S);
  1009.             vf[i] = fopen(S, "wt");
  1010.             if (!vf[i])
  1011.                 User_error("Cannot open file [%s]", S);
  1012.             fprintf(vf[i], "component 1.0 1.0 <0, 0, 0>\n");
  1013.         }
  1014.         return;
  1015.  
  1016.     } else if (blb_form) {
  1017.         strcpy(S, "output.blb");
  1018.         Message("Blob file      : %s\n", S);
  1019.         volume_file = fopen(S, "wt");
  1020.         if (!volume_file)
  1021.             User_error("Cannot open file [%s]", S);
  1022.         Buffer_IO(volume_file, 0);
  1023.         fprintf(volume_file, "[blob]\nThreshold = 0.5\n");
  1024.         return;
  1025.  
  1026.     } else if (dxf1) {
  1027.         strcpy(S, "output.dxf");
  1028.         Message("Dxf file       : %s\n", S);
  1029.         volume_file = fopen(S, "wt");
  1030.         if (!volume_file)
  1031.             User_error("Cannot open file [%s]", S);
  1032.         Buffer_IO(volume_file, 0);
  1033.  
  1034.         fprintf(volume_file, "999\nL-System Parser/Mutator\n");
  1035.         fprintf(volume_file, "999\nPolyline Polyface Meshes\n");
  1036.  
  1037.         if (user_form) {                   /* in this case build a block
  1038.                                             * section, include the loaded shape
  1039.                                             * and use only block inserts in the
  1040.                                             * entities section of the dxf file */
  1041.  
  1042.             fprintf(volume_file, "0\nSECTION\n2\nTABLES\n0\nTABLE\n2\nAPPID\n70\n4\n0\nAPPID\n2\nLPARSER\n70\n0\n0\nENDTAB\n0\nENDSEC\n");
  1043.  
  1044.             fprintf(volume_file, "0\nSECTION\n2\nBLOCKS\n0\nBLOCK\n8\n0\n2\nBLOCK\n70\n0\n");
  1045.             fprintf(volume_file, "10\n0.0\n20\n0.0\n30\n0.0\n3\nBLOCK\n");
  1046.  
  1047.             fprintf(volume_file, "0\nPOLYLINE\n66\n1\n8\n0\n62\n0\n70\n64\n");
  1048.             fprintf(volume_file, "1001\nLPARSER\n1071\n18500\n1070\n11003\n1000\n<byblock>\n1070\n10999\n");
  1049.  
  1050.             for (i = 1; i <= form_ver; i++) {
  1051.                 fprintf(volume_file, "0\nVERTEX\n8\n0\n62\n0\n");
  1052.                 fprintf(volume_file, "10\n%g\n", form_c[i][_x]);
  1053.                 fprintf(volume_file, "20\n%g\n", form_c[i][_y]);
  1054.                 fprintf(volume_file, "30\n%g\n", form_c[i][_z]);
  1055.                 fprintf(volume_file, "70\n192\n");
  1056.             }
  1057.  
  1058.             for (i = 1; i <= form_pol; i++) {
  1059.                 fprintf(volume_file, "0\nVERTEX\n8\n0\n62\n0\n");
  1060.                 fprintf(volume_file, "10\n0\n20\n0\n30\n0\n70\n128\n");
  1061.                 fprintf(volume_file, "71\n%d\n", form_s[i][0]);
  1062.                 fprintf(volume_file, "72\n%d\n", form_s[i][1]);
  1063.                 fprintf(volume_file, "73\n%d\n", form_s[i][2]);
  1064.                 fprintf(volume_file, "74\n%d\n", form_s[i][3]);
  1065.             };
  1066.  
  1067.             fprintf(volume_file, "0\nSEQEND\n8\n0\n0\nENDBLK\n8\n0\n0\nENDSEC\n");
  1068.         };
  1069.  
  1070.         fprintf(volume_file, "0\nSECTION\n2\nENTITIES\n");
  1071.  
  1072.     } else if (dxf2) {
  1073.         strcpy(S, "output.dxf");
  1074.         Message("Dxf file       : %s\n", S);
  1075.         volume_file = fopen(S, "wt");
  1076.         if (!volume_file)
  1077.             User_error("Cannot open file [%s]", S);
  1078.         Buffer_IO(volume_file, 0);
  1079.  
  1080.         fprintf(volume_file, "999\nL-System Parser/Mutator\n");
  1081.         fprintf(volume_file, "999\n3d Faces List\n");
  1082.  
  1083.         fprintf(volume_file, "0\nSECTION\n2\nENTITIES\n");
  1084.  
  1085.     } else if (dxf3) {
  1086.         strcpy(S, "output.raw");
  1087.         Message("Raw file       : %s\n", S);
  1088.         volume_file = fopen(S, "wt");
  1089.         if (!volume_file)
  1090.             User_error("Cannot open file [%s]", S);
  1091.         Buffer_IO(volume_file, 0);
  1092.  
  1093.     } else if (vrml) {
  1094.         strcpy(S, "output.wrl");
  1095.         Message("VRML file      : %s\n", S);
  1096.         volume_file = fopen(S, "wt");
  1097.         if (!volume_file)
  1098.             User_error("Cannot open file [%s]", S);
  1099.         Buffer_IO(volume_file, 0);
  1100.  
  1101.         fprintf(volume_file, "#VRML V1.0 ascii\n");     /* vrml header */
  1102.         fprintf(volume_file, "\nSeparator {\n");
  1103.         fprintf(volume_file, "\tShapeHints {\n");
  1104.         fprintf(volume_file, "\t\tvertexOrdering UNKNOWN_ORDERING\n");
  1105.         fprintf(volume_file, "\t\tshapeType UNKNOWN_SHAPE_TYPE\n");
  1106.         fprintf(volume_file, "\t\tfaceType CONVEX\n");
  1107.         fprintf(volume_file, "\t\tcreaseAngle 0.5\n");
  1108.         fprintf(volume_file, "\t}\n");
  1109.         fprintf(volume_file, "\tDirectionalLight {\n");
  1110.         fprintf(volume_file, "\t\tdirection -0.3 -0.6 -0.9\n");
  1111.         fprintf(volume_file, "\t}\n");
  1112.  
  1113.     } else {                               /* default output in Lviewer VOL
  1114.                                             * format */
  1115.         strcpy(S, "output.vol");
  1116.         Message("Datafile       : %s\n", S);
  1117.         volume_file = fopen(S, "wb");
  1118.         if (!volume_file)
  1119.             User_error("Cannot open file [%s]", S);
  1120.         Buffer_IO(volume_file, 0);
  1121.  
  1122.         Fput_bin_u8(volume_file, (u8) VersionID);       /* VOL header */
  1123.         Fput_bin_r32(volume_file, (r32) 45.0);
  1124.         Fput_bin_r32(volume_file, (r32) 45.0);
  1125.         Fput_bin_r32(volume_file, (r32) 90.0);
  1126.         Fput_bin_r32(volume_file, (r32) 45.0);
  1127.         Fput_bin_r32(volume_file, (r32) 0.0);
  1128.         Fput_bin_s16(volume_file, 0);
  1129.         Fput_bin_s16(volume_file, 0);
  1130.         Fput_bin_s16(volume_file, 100);
  1131.         Fput_bin_s16(volume_file, 3000);
  1132.         Fput_bin_u16(volume_file, (u16) 0);/* stream format */
  1133.     }
  1134. }
  1135.  
  1136.  
  1137. static void
  1138. Close_datafile(void)
  1139. {                                           /* Close the different open output
  1140.                                              * files */
  1141.     s16                     i;
  1142.  
  1143.     if (pov_form3) {
  1144.         Message("Objects        : %ld\n", polcount);
  1145.         for (i = 0; i < 8; i++)
  1146.             fclose(vf[i]);
  1147.         return;
  1148.     };
  1149.  
  1150.     if (dxf1 || dxf2)
  1151.         fprintf(volume_file, "0\nENDSEC\n0\nEOF\n");
  1152.  
  1153.     if (vrml)
  1154.         fprintf(volume_file, "}\n");
  1155.  
  1156.     Message("Objects        : %ld\n", polcount);
  1157.     fclose(volume_file);
  1158. }
  1159.  
  1160.  
  1161. static void
  1162. Save_object(s16 vertices, s16 polygons, s16 color)
  1163. {                                           /* Save an object from store to
  1164.                                              * disc */
  1165.     s32                     t, i, max;
  1166.  
  1167.     if (pov_form2 || pov_form3 || blb_form)/* in these case no 'real' geometry
  1168.                                             * is saved */
  1169.         return;
  1170.  
  1171.     polcount += polygons;
  1172.  
  1173.     if (pov_form) {
  1174.         for (t = 1; t <= polygons; t++) {
  1175.  
  1176.             if (Invalid_polygon(t))
  1177.                 continue;
  1178.  
  1179.             if (poly_store[t][2] == poly_store[t][3]) { /* 3 vertex triangle */
  1180.                 fprintf(volume_file, "object{triangle{");
  1181.                 fprintf(volume_file, "<%g, %g, %g>", ver[poly_store[t][0]][_x],
  1182.                         ver[poly_store[t][0]][_z], ver[poly_store[t][0]][_y]);
  1183.                 fprintf(volume_file, "<%g, %g, %g>", ver[poly_store[t][1]][_x],
  1184.                         ver[poly_store[t][1]][_z], ver[poly_store[t][1]][_y]);
  1185.                 fprintf(volume_file, "<%g, %g, %g>}", ver[poly_store[t][2]][_x],
  1186.                         ver[poly_store[t][2]][_z], ver[poly_store[t][2]][_y]);
  1187.                 fprintf(volume_file, "finish{t_leaf} pigment{color col_%d}}\n", color % 16);
  1188.  
  1189.             } else {                       /* 4 vertex polygon == 2x triangle */
  1190.                 fprintf(volume_file, "object{triangle{");
  1191.                 fprintf(volume_file, "<%g, %g, %g>", ver[poly_store[t][0]][_x],
  1192.                         ver[poly_store[t][0]][_z], ver[poly_store[t][0]][_y]);
  1193.                 fprintf(volume_file, "<%g, %g, %g>", ver[poly_store[t][1]][_x],
  1194.                         ver[poly_store[t][1]][_z], ver[poly_store[t][1]][_y]);
  1195.                 fprintf(volume_file, "<%g, %g, %g>}", ver[poly_store[t][2]][_x],
  1196.                         ver[poly_store[t][2]][_z], ver[poly_store[t][2]][_y]);
  1197.                 fprintf(volume_file, "finish{t_leaf} pigment{color col_%d}}\n", color % 16);
  1198.                 fprintf(volume_file, "object{triangle{");
  1199.                 fprintf(volume_file, "<%g, %g, %g>", ver[poly_store[t][2]][_x],
  1200.                         ver[poly_store[t][2]][_z], ver[poly_store[t][2]][_y]);
  1201.                 fprintf(volume_file, "<%g, %g, %g>", ver[poly_store[t][3]][_x],
  1202.                         ver[poly_store[t][3]][_z], ver[poly_store[t][3]][_y]);
  1203.                 fprintf(volume_file, "<%g, %g, %g>}", ver[poly_store[t][0]][_x],
  1204.                         ver[poly_store[t][0]][_z], ver[poly_store[t][0]][_y]);
  1205.                 fprintf(volume_file, "finish{t_leaf} pigment{color col_%d}}\n", color % 16);
  1206.             }
  1207.         }
  1208.  
  1209.     } else if (dxf1) {                     /* dxf 3d mesh object */
  1210.         fprintf(volume_file, "0\nPOLYLINE\n66\n1\n8\n%d\n70\n64\n", color);
  1211.  
  1212.         for (i = 1; i <= vertices; i++) {
  1213.             fprintf(volume_file, "0\nVERTEX\n8\n%d\n", color);
  1214.             fprintf(volume_file, "10\n%g\n", ver[i][_x]);
  1215.             fprintf(volume_file, "20\n%g\n", ver[i][_y]);
  1216.             fprintf(volume_file, "30\n%g\n", ver[i][_z]);
  1217.             fprintf(volume_file, "70\n192\n");
  1218.         }
  1219.  
  1220.         for (i = 1; i <= polygons; i++) {
  1221.             if (Invalid_polygon(i))
  1222.                 continue;
  1223.             fprintf(volume_file, "0\nVERTEX\n8\n%d\n", color);
  1224.             fprintf(volume_file, "10\n0\n20\n0\n30\n0\n70\n128\n");
  1225.             fprintf(volume_file, "71\n%d\n", poly_store[i][0]);
  1226.             fprintf(volume_file, "72\n%d\n", poly_store[i][1]);
  1227.             fprintf(volume_file, "73\n%d\n", poly_store[i][2]);
  1228.             fprintf(volume_file, "74\n%d\n", poly_store[i][3]);
  1229.         }
  1230.  
  1231.         fprintf(volume_file, "0\nSEQEND\n8\n%d\n", color);
  1232.  
  1233.     } else if (dxf2) {                     /* dxf 3dface object */
  1234.         for (i = 1; i <= polygons; i++) {
  1235.  
  1236.             if (Invalid_polygon(i))
  1237.                 continue;
  1238.  
  1239.             if (poly_store[i][2] == poly_store[i][3]) { /* 3 vertex face */
  1240.                 fprintf(volume_file, "0\n3DFACE\n8\n%d\n", color);
  1241.                 fprintf(volume_file, "10\n%g\n", ver[poly_store[i][0]][_x]);
  1242.                 fprintf(volume_file, "20\n%g\n", ver[poly_store[i][0]][_y]);
  1243.                 fprintf(volume_file, "30\n%g\n", ver[poly_store[i][0]][_z]);
  1244.                 fprintf(volume_file, "11\n%g\n", ver[poly_store[i][1]][_x]);
  1245.                 fprintf(volume_file, "21\n%g\n", ver[poly_store[i][1]][_y]);
  1246.                 fprintf(volume_file, "31\n%g\n", ver[poly_store[i][1]][_z]);
  1247.                 fprintf(volume_file, "12\n%g\n", ver[poly_store[i][2]][_x]);
  1248.                 fprintf(volume_file, "22\n%g\n", ver[poly_store[i][2]][_y]);
  1249.                 fprintf(volume_file, "32\n%g\n", ver[poly_store[i][2]][_z]);
  1250.                 fprintf(volume_file, "13\n%g\n", ver[poly_store[i][2]][_x]);
  1251.                 fprintf(volume_file, "23\n%g\n", ver[poly_store[i][2]][_y]);
  1252.                 fprintf(volume_file, "33\n%g\n", ver[poly_store[i][2]][_z]);
  1253.  
  1254.             } else {                       /* 4 vertex face */
  1255.                 fprintf(volume_file, "0\n3DFACE\n8\n%d\n", color);
  1256.                 fprintf(volume_file, "10\n%g\n", ver[poly_store[i][0]][_x]);
  1257.                 fprintf(volume_file, "20\n%g\n", ver[poly_store[i][0]][_y]);
  1258.                 fprintf(volume_file, "30\n%g\n", ver[poly_store[i][0]][_z]);
  1259.                 fprintf(volume_file, "11\n%g\n", ver[poly_store[i][1]][_x]);
  1260.                 fprintf(volume_file, "21\n%g\n", ver[poly_store[i][1]][_y]);
  1261.                 fprintf(volume_file, "31\n%g\n", ver[poly_store[i][1]][_z]);
  1262.                 fprintf(volume_file, "12\n%g\n", ver[poly_store[i][2]][_x]);
  1263.                 fprintf(volume_file, "22\n%g\n", ver[poly_store[i][2]][_y]);
  1264.                 fprintf(volume_file, "32\n%g\n", ver[poly_store[i][2]][_z]);
  1265.                 fprintf(volume_file, "13\n%g\n", ver[poly_store[i][3]][_x]);
  1266.                 fprintf(volume_file, "23\n%g\n", ver[poly_store[i][3]][_y]);
  1267.                 fprintf(volume_file, "33\n%g\n", ver[poly_store[i][3]][_z]);
  1268.             }
  1269.         }
  1270.  
  1271.     } else if (vrml) {
  1272.         fprintf(volume_file, "\tSeparator {\n");
  1273.         fprintf(volume_file, "\t\tMaterial {\n");
  1274.         fprintf(volume_file, "\t\t\tdiffuseColor ");
  1275.  
  1276.         switch (color) {                   /* translate colors from lparser to
  1277.                                             * RGB values */
  1278.           case 1:
  1279.             fprintf(volume_file, "%f %f %f", 0.3, 0.3, 0.3);
  1280.             break;
  1281.           case 2:
  1282.             fprintf(volume_file, "%f %f %f", 0.8, 0.4, 0.4);
  1283.             break;
  1284.           case 3:
  1285.             fprintf(volume_file, "%f %f %f", 0.8, 0.8, 0.4);
  1286.             break;
  1287.           case 4:
  1288.             fprintf(volume_file, "%f %f %f", 0.4, 0.8, 0.4);
  1289.             break;
  1290.           case 5:
  1291.             fprintf(volume_file, "%f %f %f", 0.4, 0.8, 0.8);
  1292.             break;
  1293.           case 6:
  1294.             fprintf(volume_file, "%f %f %f", 0.4, 0.4, 0.8);
  1295.             break;
  1296.           case 7:
  1297.             fprintf(volume_file, "%f %f %f", 0.8, 0.4, 0.8);
  1298.             break;
  1299.           case 8:
  1300.             fprintf(volume_file, "%f %f %f", 0.2, 0.5, 0.2);
  1301.             break;
  1302.           case 9:
  1303.             fprintf(volume_file, "%f %f %f", 0.2, 0.5, 0.5);
  1304.             break;
  1305.           case 10:
  1306.             fprintf(volume_file, "%f %f %f", 0.2, 0.2, 0.5);
  1307.             break;
  1308.           case 11:
  1309.             fprintf(volume_file, "%f %f %f", 0.5, 0.2, 0.5);
  1310.             break;
  1311.           case 12:
  1312.             fprintf(volume_file, "%f %f %f", 0.6, 0.2, 0.2);
  1313.             break;
  1314.           case 13:
  1315.             fprintf(volume_file, "%f %f %f", 0.5, 0.5, 0.5);
  1316.             break;
  1317.           case 14:
  1318.             fprintf(volume_file, "%f %f %f", 0.7, 0.7, 0.7);
  1319.             break;
  1320.           case 15:
  1321.             fprintf(volume_file, "%f %f %f", 0.9, 0.9, 0.9);
  1322.             break;
  1323.           default:
  1324.             fprintf(volume_file, "%f %f %f", 0.5, 0.5, 0.5);
  1325.             break;
  1326.         };
  1327.  
  1328.         fprintf(volume_file, "\n\t\t}\n");
  1329.  
  1330.     /* Write vertices */
  1331.         fprintf(volume_file, "\t\tCoordinate3 {\n");
  1332.         fprintf(volume_file, "\t\t\tpoint [\n");
  1333.         for (t = 1; t < vertices; t++)
  1334.             fprintf(volume_file, "\t\t\t\t%f %f %f,\n", ver[t][_x], ver[t][_z], ver[t][_y]);
  1335.         for (t = vertices; t <= vertices; t++)
  1336.             fprintf(volume_file, "\t\t\t\t%f %f %f\n", ver[t][_x], ver[t][_z], ver[t][_y]);
  1337.         fprintf(volume_file, "\t\t\t]\n");
  1338.         fprintf(volume_file, "\t\t}\n");
  1339.  
  1340.         fprintf(volume_file, "\t\tMaterialBinding {\n\t\t\tvalue OVERALL\n\t\t}\n");
  1341.  
  1342.     /* Write polygons */
  1343.         fprintf(volume_file, "\t\tIndexedFaceSet {\n");
  1344.         fprintf(volume_file, "\t\t\tcoordIndex [\n");
  1345.         for (t = 1; t < polygons; t++) {
  1346.             fprintf(volume_file, "\t\t\t\t");
  1347.             if (poly_store[t][2] == poly_store[t][3])
  1348.                 max = 2;
  1349.             else
  1350.                 max = 3;
  1351.             for (i = 0; i <= max; i++)
  1352.                 fprintf(volume_file, "%d, ", poly_store[t][i] - 1);
  1353.             fprintf(volume_file, "-1,\n");
  1354.         }
  1355.         for (t = polygons; t <= polygons; t++) {
  1356.             fprintf(volume_file, "\t\t\t\t");
  1357.             if (poly_store[t][2] == poly_store[t][3])
  1358.                 max = 2;
  1359.             else
  1360.                 max = 3;
  1361.             for (i = 0; i <= max; i++)
  1362.                 fprintf(volume_file, "%d, ", poly_store[t][i] - 1);
  1363.             fprintf(volume_file, "-1\n");
  1364.         }
  1365.         fprintf(volume_file, "\t\t\t]\n");
  1366.         fprintf(volume_file, "\t\t}\n");
  1367.  
  1368.         fprintf(volume_file, "\t}\n");
  1369.  
  1370.     } else if (dxf3) {                     /* simple raw format */
  1371.         for (i = 1; i <= polygons; i++) {
  1372.  
  1373.             if (Invalid_polygon(i))
  1374.                 continue;
  1375.  
  1376.             if (poly_store[i][2] == poly_store[i][3]) { /* 3 vertex triangle */
  1377.                 fprintf(volume_file, "%g ", ver[poly_store[i][0]][_x]);
  1378.                 fprintf(volume_file, "%g ", ver[poly_store[i][0]][_y]);
  1379.                 fprintf(volume_file, "%g ", ver[poly_store[i][0]][_z]);
  1380.                 fprintf(volume_file, "%g ", ver[poly_store[i][1]][_x]);
  1381.                 fprintf(volume_file, "%g ", ver[poly_store[i][1]][_y]);
  1382.                 fprintf(volume_file, "%g ", ver[poly_store[i][1]][_z]);
  1383.                 fprintf(volume_file, "%g ", ver[poly_store[i][2]][_x]);
  1384.                 fprintf(volume_file, "%g ", ver[poly_store[i][2]][_y]);
  1385.                 fprintf(volume_file, "%g\n", ver[poly_store[i][2]][_z]);
  1386.  
  1387.             } else {                       /* 4 vertex polygon = 2x triangle */
  1388.                 fprintf(volume_file, "%g ", ver[poly_store[i][0]][_x]);
  1389.                 fprintf(volume_file, "%g ", ver[poly_store[i][0]][_y]);
  1390.                 fprintf(volume_file, "%g ", ver[poly_store[i][0]][_z]);
  1391.                 fprintf(volume_file, "%g ", ver[poly_store[i][1]][_x]);
  1392.                 fprintf(volume_file, "%g ", ver[poly_store[i][1]][_y]);
  1393.                 fprintf(volume_file, "%g ", ver[poly_store[i][1]][_z]);
  1394.                 fprintf(volume_file, "%g ", ver[poly_store[i][2]][_x]);
  1395.                 fprintf(volume_file, "%g ", ver[poly_store[i][2]][_y]);
  1396.                 fprintf(volume_file, "%g\n", ver[poly_store[i][2]][_z]);
  1397.                 fprintf(volume_file, "%g ", ver[poly_store[i][0]][_x]);
  1398.                 fprintf(volume_file, "%g ", ver[poly_store[i][0]][_y]);
  1399.                 fprintf(volume_file, "%g ", ver[poly_store[i][0]][_z]);
  1400.                 fprintf(volume_file, "%g ", ver[poly_store[i][2]][_x]);
  1401.                 fprintf(volume_file, "%g ", ver[poly_store[i][2]][_y]);
  1402.                 fprintf(volume_file, "%g ", ver[poly_store[i][2]][_z]);
  1403.                 fprintf(volume_file, "%g ", ver[poly_store[i][3]][_x]);
  1404.                 fprintf(volume_file, "%g ", ver[poly_store[i][3]][_y]);
  1405.                 fprintf(volume_file, "%g\n", ver[poly_store[i][3]][_z]);
  1406.             }
  1407.         }
  1408.  
  1409.     } else {                               /* standard VOL output */
  1410.         Fput_bin_s16(volume_file, 20);
  1411.         Fput_bin_s16(volume_file, vertices);
  1412.         Fput_bin_s16(volume_file, polygons);
  1413.         Fput_bin_s16(volume_file, color);
  1414.  
  1415.         for (t = 1; t <= vertices; t++) {
  1416.             Fput_bin_r32(volume_file, ver[t][_x]);
  1417.             Fput_bin_r32(volume_file, ver[t][_y]);
  1418.             Fput_bin_r32(volume_file, ver[t][_z]);
  1419.         }
  1420.  
  1421.         for (t = 1; t <= polygons; t++) {
  1422.             for (i = 0; i <= 3; i++)
  1423.                 Fput_bin_s16(volume_file, poly_store[t][i]);
  1424.         }
  1425.     }
  1426. }
  1427.  
  1428.  
  1429. /* Add object ------------------------------------------------------------- */
  1430.  
  1431.  
  1432. static void
  1433. Inverse(vector t, vector v)
  1434. {                                           /* Inverse vector transform of a
  1435.                                              * matrix built in C123 */
  1436.     v[_x] = C1[_x] * t[_x] + C2[_x] * t[_y] + C3[_x] * t[_z];
  1437.     v[_y] = C1[_y] * t[_x] + C2[_y] * t[_y] + C3[_y] * t[_z];
  1438.     v[_z] = C1[_z] * t[_x] + C2[_z] * t[_y] + C3[_z] * t[_z];
  1439. }
  1440.  
  1441.  
  1442. static void
  1443. Set_ECS(vector n)
  1444. {                                           /* Build an ECS transform in the
  1445.                                              * axis_xyz vars, used for dxf1
  1446.                                              * output */
  1447.     vector                  Wy, Wz;
  1448.     r32                     fac = (r32) 0.015625;
  1449.  
  1450.     Wy[_x] = (r32) 0.0;
  1451.     Wy[_y] = (r32) 1.0;
  1452.     Wy[_z] = (r32) 0.0;
  1453.  
  1454.     Wz[_x] = (r32) 0.0;
  1455.     Wz[_y] = (r32) 0.0;
  1456.     Wz[_z] = (r32) 1.0;
  1457.  
  1458.     Vector_copy_r32(n, axis_z);
  1459.     Vector_normalize(axis_z);
  1460.  
  1461.     if ((Abs_r32(n[_x]) < fac) && (Abs_r32(n[_y]) < fac)) {
  1462.         Vector_product(Wy, axis_z, axis_x);
  1463.     } else {
  1464.         Vector_product(Wz, axis_z, axis_x);
  1465.     }
  1466.  
  1467.     Vector_normalize(axis_x);
  1468.     Vector_product(axis_z, axis_x, axis_y);
  1469.     Vector_normalize(axis_y);
  1470. }
  1471.  
  1472.  
  1473. static void
  1474. Inverse_ECS(vector p1, vector p2)
  1475. {                                           /* Used for dxf1 output */
  1476.     p2[_x] = axis_x[_x] * p1[_x] + axis_x[_y] * p1[_y] + axis_x[_z] * p1[_z];
  1477.     p2[_y] = axis_y[_x] * p1[_x] + axis_y[_y] * p1[_y] + axis_y[_z] * p1[_z];
  1478.     p2[_z] = axis_z[_x] * p1[_x] + axis_z[_y] * p1[_y] + axis_z[_z] * p1[_z];
  1479. }
  1480.  
  1481.  
  1482. static void
  1483. Read_form(void)
  1484. {                                           /* Read in and store an external
  1485.                                              * object */
  1486.     s32                     i, j;
  1487.     s16                     ver, pol, k;
  1488.     r32                     LR, LE, LT;
  1489.     r32                     Dum32;
  1490.     s16                     Dum16;
  1491.  
  1492.     if (pov_form || pov_form2 || pov_form3 || blb_form)
  1493.         return;
  1494.  
  1495.     strcat(x_name, ".vol");
  1496.     volume_file = fopen(x_name, "rb");
  1497.     if (!volume_file)
  1498.         User_error("Cannot open file [%s]", x_name);
  1499.  
  1500.     Buffer_IO(volume_file, 0);
  1501.  
  1502.     Dum16 = getc(volume_file);
  1503.     Set_lowhigh((Dum16 == 11));            /* get storage mode */
  1504.  
  1505.     Fget_bin_r32(volume_file, &Dum32);     /* header */
  1506.     Fget_bin_r32(volume_file, &Dum32);
  1507.     Fget_bin_r32(volume_file, &LR);
  1508.     Fget_bin_r32(volume_file, &LE);
  1509.     Fget_bin_r32(volume_file, <);
  1510.     fread(&Dum16, sizeof(s16), 1, volume_file);
  1511.     fread(&Dum16, sizeof(s16), 1, volume_file);
  1512.     fread(&Dum16, sizeof(s16), 1, volume_file);
  1513.     fread(&Dum16, sizeof(s16), 1, volume_file);
  1514.     fread(&Dum16, sizeof(u16), 1, volume_file);
  1515.  
  1516.     form_ver = 0;
  1517.     form_pol = 0;
  1518.     k = 0;
  1519.  
  1520.     for (;;) {
  1521.         if (feof(volume_file))
  1522.             break;
  1523.  
  1524.         Fget_bin_s16(volume_file, &Dum16);
  1525.         Fget_bin_s16(volume_file, &ver);   /* vertex count */
  1526.         Fget_bin_s16(volume_file, &pol);   /* polygon count */
  1527.         Fget_bin_s16(volume_file, &Dum16);
  1528.  
  1529.         for (i = 1; i <= ver; i++) {       /* vertices */
  1530.             form_ver++;
  1531.             Fget_bin_r32(volume_file, &form_c[form_ver][_x]);
  1532.             Fget_bin_r32(volume_file, &form_c[form_ver][_y]);
  1533.             Fget_bin_r32(volume_file, &form_c[form_ver][_z]);
  1534.         }
  1535.  
  1536.         for (i = 1; i <= pol; i++) {       /* polygons */
  1537.             form_pol++;
  1538.             for (j = 0; j <= 3; j++)
  1539.                 Fget_bin_s16(volume_file, &form_s[form_pol][j]);
  1540.             for (j = 0; j <= 3; j++)
  1541.                 form_s[form_pol][j] += k;
  1542.         }
  1543.  
  1544.         k = form_ver;
  1545.     }
  1546.  
  1547.     fclose(volume_file);
  1548. }
  1549.  
  1550.  
  1551. static void
  1552. Define_form(vector p1, vector p2, vector up, s16 c)
  1553. {                                           /* Insert external object. The
  1554.                                              * basis is to create the resulting
  1555.                                              * normalized direction vectors
  1556.                                              * from the turtle vectors and use
  1557.                                              * this a matrix for inverse
  1558.                                              * transforming the object from its
  1559.                                              * location round the origin to its
  1560.                                              * location at the turtle origin */
  1561.     vector                  dis, d1, d2, d3, in, ext, Q, P;
  1562.     s16                     i;
  1563.     r32                     s, d, r1, r2;
  1564.     char                    layer[10] = "";
  1565.  
  1566.  /* p1 = location, p2 = forward, up = up */
  1567.     zmin = MIN(zmin, p1[_z]);
  1568.     zmin = MIN(zmin, p2[_z]);
  1569.  
  1570.  /* setup */
  1571.     Vector_min(p2, p1, dis);
  1572.     d = Vector_length(dis);
  1573.     if (d == (r32) 0.0)
  1574.         return;
  1575.     s = d * thick;
  1576.     s = (s < (r32) min_thick) ? min_thick : s;
  1577.  
  1578.  /* d1 */
  1579.     Vector_copy_r32(dis, d1);
  1580.     Vector_normalize(d1);
  1581.  
  1582.     if (dxf1) {                            /* setup ECS and insert the block
  1583.                                             * reference */
  1584.         Set_ECS(d1);
  1585.         Inverse_ECS(p1, d2);
  1586.         Vector_copy(d1, ext);
  1587.         Vector_copy(d2, in);
  1588.         sprintf(layer, "%d", c);
  1589.         fprintf(volume_file, "0\nINSERT\n8\n%s\n2\nBLOCK\n", layer);
  1590.         fprintf(volume_file, "10\n%g\n20\n%g\n30\n%g\n", in[_x], in[_y], in[_z]);
  1591.         fprintf(volume_file, "41\n%g\n42\n%g\n43\n%g\n", s, s, d);
  1592.         fprintf(volume_file, "210\n%g\n220\n%g\n230\n%g\n", ext[_x], ext[_y], ext[_z]);
  1593.         polcount++;
  1594.         return;
  1595.     };
  1596.  
  1597.  /* d2 */
  1598.     Vector_copy_r32(up, d2);
  1599.     Vector_normalize(d2);
  1600.  
  1601.  /* d3 */
  1602.     Vector_product(d1, d2, d3);
  1603.     Vector_normalize(d3);
  1604.  
  1605.  /* setup transform */
  1606.     Vector_copy_r32(d3, C1);               /* new x-axis */
  1607.     Vector_copy_r32(d2, C2);               /* new y-axis */
  1608.     Vector_copy_r32(d1, C3);               /* new z-axis */
  1609.  
  1610.     if (pov_form) {                        /* insert a reference to l_base */
  1611.         d *= 0.7;
  1612.         s *= 0.7;
  1613.         r1 = 57.0 * Do_angle(0.0, 0.0, d1[_z], sqrt(d1[_x] * d1[_x] + d1[_y] * d1[_y]));
  1614.         r2 = 57.0 * Do_angle(0.0, 0.0, d1[_x], d1[_y]);
  1615.         fprintf(volume_file, "object{l_base ");
  1616.         fprintf(volume_file, "finish{t_base} pigment{color col_%d}", c % 16);
  1617.         fprintf(volume_file, "scale<%g, %g, %g>", s, d, s);
  1618.         fprintf(volume_file, "rotate<%g, %g, %g>", 0.0, 0.0, -r1);
  1619.         fprintf(volume_file, "rotate<%g, %g, %g>", 0.0, -r2, 0.0);
  1620.         fprintf(volume_file, "translate<%g, %g, %g>}\n", p1[_x], p1[_z], p1[_y]);
  1621.         polcount++;
  1622.         return;
  1623.  
  1624.     } else if (pov_form2) {                /* write out a blob origin */
  1625.         fprintf(volume_file, "component 1.0 %g <%g, %g, %g>\n", d, p1[_x], p1[_z], p1[_y]);
  1626.         polcount++;
  1627.         return;
  1628.  
  1629.     } else if (pov_form3) {                /* write out a blob origin to the
  1630.                                             * file based on the color */
  1631.         fprintf(vf[c % 8], "component 1.0 %g <%g, %g, %g>\n", d, p1[_x], p1[_z], p1[_y]);
  1632.         polcount++;
  1633.         return;
  1634.  
  1635.     } else if (blb_form) {                 /* write out a blob in BLB format */
  1636.         fprintf(volume_file, "Sphere = %g %g %g 1.0 %g\n", p1[_x], p1[_z], p1[_y], d);
  1637.         polcount++;
  1638.         return;
  1639.     };
  1640.  
  1641.  /* Else use the good old Lviewer VOL format */
  1642.     for (i = 1; i <= form_ver; i++) {      /* vertices */
  1643.         Q[_x] = form_c[i][_x] * s;
  1644.         Q[_y] = form_c[i][_y] * s;
  1645.         Q[_z] = form_c[i][_z] * d;
  1646.         Inverse(Q, P);
  1647.         Vector_plus(P, p1, ver[i]);
  1648.     }
  1649.  
  1650.     for (i = 1; i <= form_pol; i++) {      /* polygons */
  1651.         poly_store[i][0] = form_s[i][0];
  1652.         poly_store[i][1] = form_s[i][1];
  1653.         poly_store[i][2] = form_s[i][2];
  1654.         poly_store[i][3] = form_s[i][3];
  1655.     }
  1656.  
  1657.     Save_object(form_ver, form_pol, c);    /* save the stored object */
  1658. }
  1659.  
  1660.  
  1661. static void
  1662. Define_block(vector p1, vector p2, vector up, s16 c)
  1663. {                                           /* Insert basic block. Here we
  1664.                                              * build a cube shape directly on
  1665.                                              * the input vectors. */
  1666.     vector                  dis, d1, d2, d3;
  1667.     s16                     i;
  1668.     r32                     s, d;
  1669.  
  1670.     if (pov_form || pov_form2 || pov_form3 || blb_form)
  1671.         return;
  1672.  
  1673.     zmin = MIN(zmin, p1[_z]);
  1674.     zmin = MIN(zmin, p2[_z]);
  1675.  
  1676.  /* setup */
  1677.     Vector_min(p2, p1, dis);
  1678.     d = Vector_length(dis);
  1679.     if (d == (r32) 0.0)
  1680.         return;
  1681.     s = d * thick;
  1682.     s = (s < (r32) min_thick) ? min_thick : s;
  1683.     s *= 0.5;
  1684.  
  1685.  /* d1 */
  1686.     Vector_copy_r32(dis, d1);
  1687.     Vector_normalize(d1);
  1688.  
  1689.  /* d2 */
  1690.     Vector_copy_r32(up, d2);
  1691.     Vector_normalize(d2);
  1692.  
  1693.  /* d3 */
  1694.     Vector_product(d1, d2, d3);
  1695.     Vector_normalize(d3);
  1696.  
  1697.  /* base 1, 3 */
  1698.     Vector_plus(d2, d3, d1);
  1699.     Vector_normalize(d1);
  1700.     Vector_plus_fac(p1, d1, s, ver[1]);
  1701.     Vector_plus_fac(p1, d1, -s, ver[3]);
  1702.  
  1703.  /* base 2, 4 */
  1704.     Vector_min(d2, d3, d1);
  1705.     Vector_normalize(d1);
  1706.     Vector_plus_fac(p1, d1, s, ver[2]);
  1707.     Vector_plus_fac(p1, d1, -s, ver[4]);
  1708.  
  1709.  /* end */
  1710.     for (i = 1; i <= 4; i++)
  1711.         Vector_plus(ver[i], dis, ver[i + 4]);
  1712.  
  1713.  /* polygons */
  1714.     poly_store[1][0] = 1;
  1715.     poly_store[1][1] = 5;
  1716.     poly_store[1][2] = 6;
  1717.     poly_store[1][3] = 2;
  1718.  
  1719.     poly_store[2][0] = 2;
  1720.     poly_store[2][1] = 6;
  1721.     poly_store[2][2] = 7;
  1722.     poly_store[2][3] = 3;
  1723.  
  1724.     poly_store[3][0] = 3;
  1725.     poly_store[3][1] = 7;
  1726.     poly_store[3][2] = 8;
  1727.     poly_store[3][3] = 4;
  1728.  
  1729.     poly_store[4][0] = 4;
  1730.     poly_store[4][1] = 8;
  1731.     poly_store[4][2] = 5;
  1732.     poly_store[4][3] = 1;
  1733.  
  1734.     poly_store[5][0] = 1;
  1735.     poly_store[5][1] = 2;
  1736.     poly_store[5][2] = 3;
  1737.     poly_store[5][3] = 4;
  1738.  
  1739.     poly_store[6][0] = 8;
  1740.     poly_store[6][1] = 7;
  1741.     poly_store[6][2] = 6;
  1742.     poly_store[6][3] = 5;
  1743.  
  1744.     Save_object(8, 6, c);
  1745. }
  1746.  
  1747.  
  1748. static void
  1749. Define_closed(vector p1, vector p2, vector up, s16 c)
  1750. {                                           /* Insert connected cylinder shape.
  1751.                                              * The lastxxx vars are used to
  1752.                                              * store the previous top of the
  1753.                                              * cylinder for conntecing a next
  1754.                                              * one. Since the vars are stacked
  1755.                                              * for [] we can connect correctly
  1756.                                              * according to current nesting
  1757.                                              * level. */
  1758.     vector                  dis, d1, d2, d3, t1, t2;
  1759.     s16                     i, ii, col;
  1760.     r32                     s, d, dd = float_max;
  1761.  
  1762.     if (pov_form || pov_form2 || pov_form3 || blb_form)
  1763.         return;
  1764.  
  1765.     zmin = MIN(zmin, p1[_z]);
  1766.     zmin = MIN(zmin, p2[_z]);
  1767.  
  1768.  /* setup */
  1769.     Vector_min(p2, p1, dis);
  1770.     d = Vector_length(dis);
  1771.     if (d == (r32) 0.0)
  1772.         return;
  1773.     s = d * thick;
  1774.     s = (s < (r32) min_thick) ? min_thick : s;
  1775.     s *= 0.5;
  1776.  
  1777.  /* d1 */
  1778.     Vector_copy_r32(dis, d1);
  1779.     Vector_normalize(d1);
  1780.  
  1781.  /* d2 */
  1782.     Vector_copy_r32(up, d2);
  1783.     Vector_normalize(d2);
  1784.  
  1785.  /* d3 */
  1786.     Vector_product(d1, d2, d3);
  1787.     Vector_normalize(d3);
  1788.  
  1789.     Vector_plus(d2, d3, t1);
  1790.     Vector_normalize(t1);
  1791.     Vector_min(d2, d3, t2);
  1792.     Vector_normalize(t2);
  1793.  
  1794.     Vector_plus_fac(p1, t1, s, ver[1]);
  1795.     Vector_plus_fac(p1, t1, -s, ver[5]);
  1796.     Vector_plus_fac(p1, t2, s, ver[3]);
  1797.     Vector_plus_fac(p1, t2, -s, ver[7]);
  1798.  
  1799.     s *= (r32) 0.7071;
  1800.     Vector_plus_fac2(p1, t1, s, t2, s, ver[2]);
  1801.     Vector_plus_fac2(p1, t1, -s, t2, s, ver[4]);
  1802.     Vector_plus_fac2(p1, t1, -s, t2, -s, ver[6]);
  1803.     Vector_plus_fac2(p1, t1, s, t2, -s, ver[8]);
  1804.  
  1805.  /* end */
  1806.     for (i = 1; i <= 8; i++)
  1807.         Vector_plus(ver[i], dis, ver[i + 8]);
  1808.  
  1809.     if (last_col == c) {
  1810.         Vector_min(p1, last, dis);
  1811.         d = Vector_length(dis);
  1812.  
  1813.         if (d < (r32) 1.0) {
  1814.             for (i = 1; i <= 8; i++) {
  1815.                 Vector_min(ver[1], last_v[i], dis);
  1816.                 d = Vector_length(dis);
  1817.                 if (d < dd) {
  1818.                     dd = d;
  1819.                     ii = i;
  1820.                 }
  1821.             }
  1822.             for (i = 1; i <= 8; i++) {
  1823.                 Vector_copy_r32(last_v[ii], ver[i]);
  1824.                 ii = (ii + 1) % 9;
  1825.                 if (ii == 0)
  1826.                     ii = 1;
  1827.             }
  1828.         }
  1829.     };
  1830.  
  1831.  /* polygons */
  1832.     poly_store[1][0] = 1;
  1833.     poly_store[1][1] = 9;
  1834.     poly_store[1][2] = 10;
  1835.     poly_store[1][3] = 2;
  1836.  
  1837.     poly_store[2][0] = 2;
  1838.     poly_store[2][1] = 10;
  1839.     poly_store[2][2] = 11;
  1840.     poly_store[2][3] = 3;
  1841.  
  1842.     poly_store[3][0] = 3;
  1843.     poly_store[3][1] = 11;
  1844.     poly_store[3][2] = 12;
  1845.     poly_store[3][3] = 4;
  1846.  
  1847.     poly_store[4][0] = 4;
  1848.     poly_store[4][1] = 12;
  1849.     poly_store[4][2] = 13;
  1850.     poly_store[4][3] = 5;
  1851.  
  1852.     poly_store[5][0] = 5;
  1853.     poly_store[5][1] = 13;
  1854.     poly_store[5][2] = 14;
  1855.     poly_store[5][3] = 6;
  1856.  
  1857.     poly_store[6][0] = 6;
  1858.     poly_store[6][1] = 14;
  1859.     poly_store[6][2] = 15;
  1860.     poly_store[6][3] = 7;
  1861.  
  1862.     poly_store[7][0] = 7;
  1863.     poly_store[7][1] = 15;
  1864.     poly_store[7][2] = 16;
  1865.     poly_store[7][3] = 8;
  1866.  
  1867.     poly_store[8][0] = 8;
  1868.     poly_store[8][1] = 16;
  1869.     poly_store[8][2] = 9;
  1870.     poly_store[8][3] = 1;
  1871.  
  1872.     Save_object(16, 8, c);
  1873.  
  1874.     last_col = c;
  1875.     Vector_copy_r32(p2, last);
  1876.     for (i = 1; i <= 8; i++)
  1877.         Vector_copy_r32(ver[i + 8], last_v[i]);
  1878. }
  1879.  
  1880.  
  1881. static void
  1882. Ground_plane(void)
  1883. {                                           /* Add a simple large groundplane */
  1884.     r32                     l = (r32) 1e5;
  1885.  
  1886.     ver[1][_x] = -l;
  1887.     ver[1][_y] = l;
  1888.     ver[1][_z] = zmin;
  1889.  
  1890.     ver[2][_x] = l;
  1891.     ver[2][_y] = l;
  1892.     ver[2][_z] = zmin;
  1893.  
  1894.     ver[3][_x] = l;
  1895.     ver[3][_y] = -l;
  1896.     ver[3][_z] = zmin;
  1897.  
  1898.     ver[4][_x] = -l;
  1899.     ver[4][_y] = -l;
  1900.     ver[4][_z] = zmin;
  1901.  
  1902.     poly_store[1][0] = 4;
  1903.     poly_store[1][1] = 3;
  1904.     poly_store[1][2] = 2;
  1905.     poly_store[1][3] = 1;
  1906.  
  1907.     Save_object(4, 1, 1);
  1908. }
  1909.  
  1910.  
  1911. /* L-system routines ------------------------------------------------------ */
  1912.  
  1913.  
  1914. static r32
  1915. Rnd(void)
  1916. {                                           /* Get a random number */
  1917.     return (r32) rand() * rm;
  1918. }
  1919.  
  1920.  
  1921.  
  1922. #define Util_t(In,C1,C2,C3,Out) {\
  1923.   Out[_x] = Scalar_product(C1,In);\
  1924.   Out[_y] = Scalar_product(C2,In);\
  1925.   Out[_z] = Scalar_product(C3,In);\
  1926. }
  1927.  
  1928.  
  1929. static void
  1930. Set_rot(r32 a, vector n)
  1931. {                                           /* Set up a rotation matrix */
  1932.     r32                     n11, n22, n33, nxy, nxz, nyz, sina, cosa;
  1933.  
  1934.     cosa = cos(a);
  1935.     sina = sin(a);
  1936.  
  1937.     n11 = n[_x] * n[_x];
  1938.     n22 = n[_y] * n[_y];
  1939.     n33 = n[_z] * n[_z];
  1940.  
  1941.     nxy = n[_x] * n[_y];
  1942.     nxz = n[_x] * n[_z];
  1943.     nyz = n[_y] * n[_z];
  1944.  
  1945.     C1[_x] = n11 + (one - n11) * cosa;
  1946.     C1[_y] = nxy * (one - cosa) - n[_z] * sina;
  1947.     C1[_z] = nxz * (one - cosa) + n[_y] * sina;
  1948.  
  1949.     C2[_x] = nxy * (one - cosa) + n[_z] * sina;
  1950.     C2[_y] = n22 + (one - n22) * cosa;
  1951.     C2[_z] = nyz * (one - cosa) - n[_x] * sina;
  1952.  
  1953.     C3[_x] = nxz * (one - cosa) - n[_y] * sina;
  1954.     C3[_y] = nyz * (one - cosa) + n[_x] * sina;
  1955.     C3[_z] = n33 + (one - n33) * cosa;
  1956. }
  1957.  
  1958.  
  1959. static r32
  1960. Get_value(u32 *j)
  1961. {                                           /* Read a (xx) value from a
  1962.                                              * production string at location j
  1963.                                              * and make it into a real */
  1964.     s16                     i = 0;
  1965.     r32                     r = 0.0;
  1966.     char                    val[40] = "";
  1967.  
  1968.     (*j)++;
  1969.     (*j)++;
  1970.  
  1971.     for (;;) {
  1972.         if (object_s[*j] == ')')
  1973.             break;
  1974.         val[i] = object_s[*j];
  1975.         i++;
  1976.         (*j)++;
  1977.     }
  1978.  
  1979.     val[i] = '\0';
  1980.     sscanf(val, "%f", &r);
  1981.  
  1982.     if (last_recur)
  1983.         r *= fraction;
  1984.  
  1985.     return r;
  1986. }
  1987.  
  1988.  
  1989. static
  1990. L_init(void)
  1991. {                                           /* Process a ls file and setup */
  1992.     FILE                   *f;
  1993.     char                    name[max_file], temp[rule_s];
  1994.     boolean                 found;
  1995.     s16                     i, j;
  1996.  
  1997.  /* Init mem */
  1998.     object_s = (char *) malloc(max_string);
  1999.     otemp = (char *) malloc(max_string);
  2000.     stack = (s_rec *) malloc(sizeof(s_rec) * max_stack);
  2001.     pstack = (p_rec *) malloc(sizeof(p_rec) * max_stack);
  2002.     if ((object_s == NULL) || (otemp == NULL) || (stack == NULL) || (pstack == NULL))
  2003.         User_error("Not enough memory to startup");
  2004.  
  2005.  /* Get file name */
  2006.     Get_comline_filename(name);
  2007.     strcat(name, ".ls");
  2008.     f = fopen(name, "rt");
  2009.     if (!f)
  2010.         User_error("Cannot find file [%s]", name);
  2011.     Message("L-system file  : %s\n", name);
  2012.  
  2013.  /* Recursion level */
  2014.     do {
  2015.         Fget_string(f, temp);
  2016.     } while (temp[0] == '#');
  2017.     sscanf(temp, "%f", &recursion);
  2018.     Get_comline_opt("r", &found, temp);    /* Overrule ? */
  2019.     if (found)
  2020.         sscanf(temp, "%f", &recursion);
  2021.     Message("Recursion depth: %g\n", recursion);
  2022.     lev = (s16) recursion;
  2023.     fraction = recursion - (r32) lev;
  2024.     if (fraction > zero) {                 /* Check for fraction */
  2025.         lev++;
  2026.         growing = TRUE;
  2027.     } else {
  2028.         growing = FALSE;
  2029.     }
  2030.  
  2031.  /* Basic angle */
  2032.     do {
  2033.         Fget_string(f, temp);
  2034.     } while (temp[0] == '#');
  2035.     sscanf(temp, "%f", &ang);
  2036.     Get_comline_opt("a", &found, temp);    /* Overrule ? */
  2037.     if (found)
  2038.         sscanf(temp, "%f", &ang);
  2039.     Message("Basic angle    : %g\n", ang);
  2040.     ang = (ang / 180.0) * 3.141592654;
  2041.  
  2042.  /* Thickness */
  2043.     do {
  2044.         Fget_string(f, temp);
  2045.     } while (temp[0] == '#');
  2046.     sscanf(temp, "%f", &thick);
  2047.     Message("Thickness      : %g\n", thick);
  2048.     thick /= 100.0;
  2049.  
  2050.  /* Axiom */
  2051.     do {
  2052.         Fget_string(f, temp);
  2053.     } while (temp[0] == '#');
  2054.     strcpy(object_s, strtok(temp, " \r\n\t#"));
  2055.     Message("Axiom          : %s\n", object_s);
  2056.  
  2057.  /* Get rules */
  2058.     num = 0;
  2059.     for (i = 0; i < 150; i++) {
  2060.         do {
  2061.             Fget_string(f, temp);
  2062.         } while (temp[0] == '#');
  2063.         strcpy(rule[num], strtok(temp, " \r\n\t#"));
  2064.         if (rule[num][0] == '\0')
  2065.             continue;
  2066.         if (rule[num][0] == '@')
  2067.             break;
  2068.         num++;
  2069.     };
  2070.  
  2071.     fclose(f);
  2072.  
  2073.  /* Add default rules */
  2074.     strcpy(rule[num++], "+=+");
  2075.     strcpy(rule[num++], "-=-");
  2076.     strcpy(rule[num++], "&=&");
  2077.     strcpy(rule[num++], "^=^");
  2078.     strcpy(rule[num++], "<=<");
  2079.     strcpy(rule[num++], ">=>");
  2080.  
  2081.     strcpy(rule[num++], "%=%");
  2082.     strcpy(rule[num++], "|=|");
  2083.     strcpy(rule[num++], "!=!");
  2084.     strcpy(rule[num++], "?=?");
  2085.     strcpy(rule[num++], ":=:");
  2086.     strcpy(rule[num++], ";=;");
  2087.     strcpy(rule[num++], "\'=\'");
  2088.     strcpy(rule[num++], "\"=\"");
  2089.     strcpy(rule[num++], "c=c");
  2090.  
  2091.     strcpy(rule[num++], "[=[");
  2092.     strcpy(rule[num++], "]=]");
  2093.     strcpy(rule[num++], "{={");
  2094.     strcpy(rule[num++], "}=}");
  2095.  
  2096.     strcpy(rule[num++], "F=F");
  2097.     strcpy(rule[num++], "f=f");
  2098.     strcpy(rule[num++], "t=t");
  2099.     strcpy(rule[num++], "g=g");
  2100.     strcpy(rule[num++], "Z=Z");
  2101.     strcpy(rule[num++], "z=z");
  2102.     strcpy(rule[num++], "*=*");
  2103.     strcpy(rule[num++], "$=$");
  2104.     strcpy(rule[num++], "~=~");
  2105.  
  2106.     strcpy(rule[num++], ".=.");
  2107.     strcpy(rule[num++], "1=1");
  2108.     strcpy(rule[num++], "2=2");
  2109.     strcpy(rule[num++], "3=3");
  2110.     strcpy(rule[num++], "4=4");
  2111.     strcpy(rule[num++], "5=5");
  2112.     strcpy(rule[num++], "6=6");
  2113.     strcpy(rule[num++], "7=7");
  2114.     strcpy(rule[num++], "8=8");
  2115.     strcpy(rule[num++], "9=9");
  2116.     strcpy(rule[num++], "0=0");
  2117.     strcpy(rule[num++], "(=(");
  2118.     strcpy(rule[num++], ")=)");
  2119.  
  2120.     strcpy(rule[num++], "_=_");            /* closer default */
  2121.  
  2122.  /* Set start values fir F and Z distances */
  2123.     dis = 100.0;
  2124.     dis2 = dis * 0.5;
  2125.  
  2126.  /* Get sizes and marks */
  2127.     for (i = 0; i < num; i++) {
  2128.         size[i] = strlen(rule[i]) - 2;
  2129.         mark[i] = FALSE;
  2130.     };
  2131.  
  2132.  /* Check which rules need to be marked for last recursion when growing */
  2133.     for (i = 0; i < num; i++) {
  2134.         if (rule[i][0] == '+')
  2135.             break;
  2136.         mark[i] = TRUE;
  2137.  
  2138.     /* All rules with basic move/block before '=' mark false */
  2139.         if (rule[i][0] == 'F')
  2140.             mark[i] = FALSE;
  2141.         if (rule[i][0] == 'f')
  2142.             mark[i] = FALSE;
  2143.         if (rule[i][0] == 'Z')
  2144.             mark[i] = FALSE;
  2145.         if (rule[i][0] == 'z')
  2146.             mark[i] = FALSE;
  2147.  
  2148.         Message("Rule           : %s\n", rule[i]);
  2149.     }
  2150. }
  2151.  
  2152.  
  2153. static
  2154. L_mutate(void)
  2155. {                                           /* Apply mutations to the rules */
  2156.     s16                     i, j, k, rules, ii, max = 1000;
  2157.     char                    T, R, S[10] = "";
  2158.     char                    rulet[100] = "";
  2159.  
  2160.     for (i = 0; i < num; i++) {
  2161.         if (rule[i][0] == '+')
  2162.             break;
  2163.     }
  2164.     rules = i;
  2165.  
  2166.     switch ((s16) (Rnd() * 6.0)) {
  2167.  
  2168.       default:
  2169.         return;
  2170.  
  2171.       case 1:                              /* Insert */
  2172.         i = (s16) (Rnd() * (r32) rules);
  2173.         T = rule[i][0];
  2174.         j = (s16) (Rnd() * (r32) rules);
  2175.         k = (s16) (Rnd() * (r32) strlen(rule[j]));
  2176.         k = (k < 2) ? 2 : k;
  2177.         strcpy(rulet, &(rule[j][k]));
  2178.         rule[j][k] = '[';
  2179.         rule[j][k + 1] = T;
  2180.         rule[j][k + 2] = ']';
  2181.         rule[j][k + 3] = '\0';
  2182.         strcat(rule[j], rulet);
  2183.         size[j] = strlen(rule[j]) - 2;
  2184.         break;
  2185.  
  2186.       case 0:
  2187.       case 2:                              /* Replace */
  2188.         do {
  2189.             i = (s16) (Rnd() * (r32) rules);
  2190.             j = (s16) (Rnd() * (r32) rules);
  2191.             T = rule[i][0];
  2192.             R = rule[j][0];
  2193.         } while (T == R);
  2194.         for (ii = 0; ii < max; ii++) {
  2195.             i = (s16) (Rnd() * (r32) rules);
  2196.             for (j = 2; j < strlen(rule[i]); j++) {
  2197.                 if (rule[i][j] == T) {
  2198.                     rule[i][j] = R;
  2199.                     return;
  2200.                 }
  2201.             }
  2202.         }
  2203.         break;
  2204.  
  2205.       case 3:                              /* Append */
  2206.         i = (s16) (Rnd() * (r32) rules);
  2207.         S[0] = rule[i][0];
  2208.         i = (s16) (Rnd() * (r32) rules);
  2209.         strcat(rule[i], S);
  2210.         size[i] = strlen(rule[i]) - 2;
  2211.         break;
  2212.  
  2213.       case 4:                              /* Swap directions */
  2214.         for (ii = 0; ii < max; ii++) {
  2215.             i = (s16) (Rnd() * (r32) rules);
  2216.             for (j = 2; j < strlen(rule[i]); j++) {
  2217.                 switch ((s16) (Rnd() * 12.0)) {
  2218.                   default:
  2219.                     return;
  2220.                   case 0:
  2221.                     if (rule[i][j] == '+') {
  2222.                         rule[i][j] = '-';
  2223.                         return;
  2224.                     }
  2225.                     break;
  2226.                   case 1:
  2227.                     if (rule[i][j] == '-') {
  2228.                         rule[i][j] = '+';
  2229.                         return;
  2230.                     }
  2231.                     break;
  2232.                   case 2:
  2233.                     if (rule[i][j] == '&') {
  2234.                         rule[i][j] = '^';
  2235.                         return;
  2236.                     }
  2237.                     break;
  2238.                   case 3:
  2239.                     if (rule[i][j] == '^') {
  2240.                         rule[i][j] = '&';
  2241.                         return;
  2242.                     }
  2243.                     break;
  2244.                   case 4:
  2245.                     if (rule[i][j] == '>') {
  2246.                         rule[i][j] = '<';
  2247.                         return;
  2248.                     }
  2249.                     break;
  2250.                   case 5:
  2251.                     if (rule[i][j] == '<') {
  2252.                         rule[i][j] = '>';
  2253.                         return;
  2254.                     }
  2255.                     break;
  2256.                   case 6:
  2257.                     if (rule[i][j] == '|') {
  2258.                         rule[i][j] = '%';
  2259.                         return;
  2260.                     }
  2261.                     break;
  2262.                   case 7:
  2263.                     if (rule[i][j] == '%') {
  2264.                         rule[i][j] = '|';
  2265.                         return;
  2266.                     }
  2267.                     break;
  2268.                   case 8:
  2269.                     if (rule[i][j] == ':') {
  2270.                         rule[i][j] = ';';
  2271.                         return;
  2272.                     }
  2273.                     break;
  2274.                   case 9:
  2275.                     if (rule[i][j] == ';') {
  2276.                         rule[i][j] = ':';
  2277.                         return;
  2278.                     }
  2279.                     break;
  2280.                   case 10:
  2281.                     if (rule[i][j] == '\'') {
  2282.                         rule[i][j] = '\"';
  2283.                         return;
  2284.                     }
  2285.                     break;
  2286.                   case 11:
  2287.                     if (rule[i][j] == '\"') {
  2288.                         rule[i][j] = '\'';
  2289.                         return;
  2290.                     }
  2291.                     break;
  2292.                 }
  2293.             }
  2294.         }
  2295.         break;
  2296.  
  2297.       case 5:                              /* Swap sizes */
  2298.         for (ii = 0; ii < max; ii++) {
  2299.             i = (s16) (Rnd() * (r32) rules);
  2300.             for (j = 2; j < strlen(rule[i]); j++) {
  2301.                 switch ((s16) (Rnd() * 6.0)) {
  2302.                   default:
  2303.                     return;
  2304.                   case 0:
  2305.                     if (rule[i][j] == 'F') {
  2306.                         rule[i][j] = 'Z';
  2307.                         return;
  2308.                     }
  2309.                     break;
  2310.                   case 1:
  2311.                     if (rule[i][j] == 'Z') {
  2312.                         rule[i][j] = 'F';
  2313.                         return;
  2314.                     }
  2315.                     break;
  2316.                   case 2:
  2317.                     if (rule[i][j] == 'f') {
  2318.                         rule[i][j] = 'z';
  2319.                         return;
  2320.                     }
  2321.                     break;
  2322.                   case 3:
  2323.                     if (rule[i][j] == 'z') {
  2324.                         rule[i][j] = 'f';
  2325.                         return;
  2326.                     }
  2327.                     break;
  2328.                   case 4:
  2329.                     if (rule[i][j] == '!') {
  2330.                         rule[i][j] = '?';
  2331.                         return;
  2332.                     }
  2333.                     break;
  2334.                   case 5:
  2335.                     if (rule[i][j] == '?') {
  2336.                         rule[i][j] = '!';
  2337.                         return;
  2338.                     }
  2339.                     break;
  2340.                 }
  2341.             }
  2342.         }
  2343.         break;
  2344.  
  2345.     }
  2346. }
  2347.  
  2348.  
  2349. static
  2350. L_system(void)
  2351. {                                           /* Expand l-system into production
  2352.                                              * string. Object_s is read with
  2353.                                              * the k counter and the next
  2354.                                              * generation is build up in otemp
  2355.                                              * with the ot counter. */
  2356.  
  2357.     u32                     k, st, s, ss, max = max_string - 10L;
  2358.     char                   *ot;
  2359.     char                    m_1 = '@';
  2360.     s16                     S[256], i, l;
  2361.     boolean                 incomplete = FALSE, marker = FALSE;
  2362.  
  2363.  /*
  2364.   * Clear fast access array. This array is to quickly find the rule asociated
  2365.   * with a char.
  2366.   */
  2367.     for (i = 0; i < 256; i++)
  2368.         S[i] = num - 1;                    /* Num -1 contains the default rule
  2369.                                             * which does nothing */
  2370.  
  2371.  /* Each char gets a rule number */
  2372.     for (i = num - 1; i >= 0; i--)
  2373.         S[(s16) rule[i][0]] = i;
  2374.  
  2375.     Process_start2(lev - 1);
  2376.  
  2377.     for (l = 0; l < lev; l++) {            /* For each recursion */
  2378.         Process_update2(l);
  2379.  
  2380.         marker = ((l == (lev - 1)) && growing); /* Need markers ? */
  2381.  
  2382.         st = strlen(object_s);
  2383.         ot = otemp;
  2384.         ss = 0;
  2385.  
  2386.         for (k = (u32) 0; k < st; k++) {   /* For each char in the string */
  2387.             i = S[object_s[k]];            /* i = rule number attached to
  2388.                                             * current char */
  2389.             s = size[i];                   /* s = size of current rule */
  2390.             ss += s;
  2391.  
  2392.             if (ss >= max) {               /* Overflow */
  2393.                 l = lev;
  2394.                 incomplete = TRUE;
  2395.                 break;
  2396.  
  2397.             } else {
  2398.                 if (marker && mark[i]) {   /* Add mark char */
  2399.                     Mem_copy(&m_1, ot, 1);
  2400.                     ot += 1;
  2401.                     Mem_copy(&(rule[i][2]), ot, s);
  2402.                     ot += s;
  2403.                     Mem_copy(&m_1, ot, 1);
  2404.                     ot += 1;
  2405.                 } else {
  2406.                     Mem_copy(&(rule[i][2]), ot, s);     /* Copy */
  2407.                     ot += s;
  2408.                 }
  2409.             }
  2410.         };
  2411.  
  2412.         *ot = '\0';
  2413.         strcpy(object_s, otemp);           /* Copy the temp string to object_s
  2414.                                             * and repeat cycle */
  2415.     };
  2416.  
  2417.     Process_end2();
  2418.     Message("Size of string : %ld chars %s\n", strlen(object_s), incomplete ? "(incomplete)" : "");
  2419. }
  2420.  
  2421.  
  2422. static void
  2423. L_save(void)
  2424. {                                           /* Save mutated ls-system for
  2425.                                              * re-run */
  2426.     FILE                   *f;
  2427.     s16                     i;
  2428.  
  2429.     remove("mutation.ls");
  2430.     f = fopen("mutation.ls", "wt");
  2431.     if (!f)
  2432.         User_error("Cannot open file [mutation.ls]");
  2433.  
  2434.     Message("Saving ls file : mutation.ls\n");
  2435.  
  2436.     fprintf(f, "%d\n", lev);
  2437.     fprintf(f, "%g\n", (ang / 3.141592654) * 180.0);
  2438.     fprintf(f, "%g\n", thick * 100.0);
  2439.  
  2440.     fprintf(f, "%s\n", object_s);
  2441.  
  2442.     for (i = 0; i < num; i++) {
  2443.         if (rule[i][0] == '+')
  2444.             break;
  2445.         fprintf(f, "%s\n", rule[i]);
  2446.     }
  2447.     fprintf(f, "@\n");
  2448.  
  2449.     fclose(f);
  2450. }
  2451.  
  2452.  
  2453.  
  2454. static
  2455. L_draw(void)
  2456. {                                           /* Process a production string and
  2457.                                              * generate form */
  2458.     vector                  pos, end, v, fow, upp, lef;
  2459.     u32                     i, max = strlen(object_s);
  2460.     r32                     r, a, thick_l, ang_l, dis_l, dis2_l, trope_l;
  2461.     s16                     vcount, pcount, j;
  2462.     char                    temp[max_file], next;
  2463.     boolean                 found, poly_on = FALSE;
  2464.     u32                     one_star, star_num;
  2465.  
  2466.  /* Echo production string */
  2467.     Get_comline_opt("l", &found, temp);
  2468.     if (found) {
  2469.         Message("Production     : ");
  2470.         for (i = 0; object_s[i] != '\0'; i++) {
  2471.             Message("%c", object_s[i]);
  2472.         }
  2473.         Message("\n");
  2474.     };
  2475.  
  2476.  /* Get user form if needed */
  2477.     if (user_form)
  2478.         Read_form();
  2479.  
  2480.  /* Setup vectors */
  2481.     pos[_x] = 0.0;
  2482.     pos[_y] = 0.0;
  2483.     pos[_z] = 0.0;
  2484.     fow[_x] = 0.0;
  2485.     fow[_y] = 0.0;
  2486.     fow[_z] = 1.0;
  2487.     lef[_x] = 0.0;
  2488.     lef[_y] = 1.0;
  2489.     lef[_z] = 0.0;
  2490.     upp[_x] = 1.0;
  2491.     upp[_y] = 0.0;
  2492.     upp[_z] = 0.0;
  2493.     Vector_normalize(trope);
  2494.  
  2495.  /* Do it */
  2496.     Open_datafile();
  2497.  
  2498.  /* Start values */
  2499.     org.col = col;
  2500.     org.dis = dis;
  2501.     org.dis2 = dis2;
  2502.     org.ang = ang;
  2503.     org.thick = thick;
  2504.     org.tr = tr;
  2505.  
  2506.  /* Feedback */
  2507.     Process_start2(strlen(object_s));
  2508.  
  2509.     for (i = 0; object_s[i] != '\0'; i++) {
  2510.         Process_update2(i);
  2511.  
  2512.         if (polcount > poly_limit)         /* overflow */
  2513.             break;
  2514.  
  2515.         next = object_s[i + 1];            /* the next char in de string */
  2516.  
  2517.         switch (object_s[i]) {             /* the current char in the string */
  2518.           default:
  2519.             break;
  2520.  
  2521.           case '@':                        /* Marks last recursion level during
  2522.                                             * growing fase */
  2523.             last_recur = !last_recur;
  2524.             if (last_recur) {              /* Store all vars and do fraction */
  2525.                 thick_l = thick;
  2526.                 ang_l = ang;
  2527.                 dis_l = dis;
  2528.                 dis2_l = dis2;
  2529.                 trope_l = trope_amount;
  2530.                 dis *= fraction;
  2531.                 dis2 *= fraction;
  2532.                 thick *= fraction;
  2533.                 ang *= fraction;
  2534.                 trope_amount *= fraction;
  2535.             } else {                       /* Restore */
  2536.                 thick = thick_l;
  2537.                 ang = ang_l;
  2538.                 dis = dis_l;
  2539.                 dis2 = dis2_l;
  2540.                 trope_amount = trope_l;
  2541.             }
  2542.             break;
  2543.  
  2544.           case '+':
  2545.             save.ang = ang;
  2546.             if (next == '(') {
  2547.                 ang = ((r32) 0.017453) * Get_value(&i);
  2548.                 if (last_recur)
  2549.                     ang *= fraction;
  2550.             }
  2551.             Set_rot(-ang, upp);
  2552.             Util_t(fow, C1, C2, C3, v);
  2553.             Vector_copy_r32(v, fow);
  2554.             Util_t(lef, C1, C2, C3, v);
  2555.             Vector_copy_r32(v, lef);
  2556.             Vector_normalize(fow);
  2557.             Vector_normalize(lef);
  2558.             ang = save.ang;
  2559.             break;
  2560.  
  2561.           case '-':
  2562.             save.ang = ang;
  2563.             if (next == '(') {
  2564.                 ang = ((r32) 0.017453) * Get_value(&i);
  2565.                 if (last_recur)
  2566.                     ang *= fraction;
  2567.             }
  2568.             Set_rot(ang, upp);
  2569.             Util_t(fow, C1, C2, C3, v);
  2570.             Vector_copy_r32(v, fow);
  2571.             Util_t(lef, C1, C2, C3, v);
  2572.             Vector_copy_r32(v, lef);
  2573.             Vector_normalize(fow);
  2574.             Vector_normalize(lef);
  2575.             ang = save.ang;
  2576.             break;
  2577.  
  2578.           case '~':
  2579.             if (next == '(')
  2580.                 r = ((r32) 0.017453) * Get_value(&i);
  2581.             else if (rand_set)
  2582.                 r = ((r32) 0.017453) * rand_amount;
  2583.             else
  2584.                 r = (r32) 6.0;
  2585.             a = (Rnd() * r * (r32) 2.0) - r;
  2586.             Set_rot(a, upp);
  2587.             Util_t(fow, C1, C2, C3, v);
  2588.             Vector_copy_r32(v, fow);
  2589.             Util_t(lef, C1, C2, C3, v);
  2590.             Vector_copy_r32(v, lef);
  2591.             Vector_normalize(fow);
  2592.             Vector_normalize(lef);
  2593.             a = (Rnd() * r * (r32) 2.0) - r;
  2594.             Set_rot(a, lef);
  2595.             Util_t(fow, C1, C2, C3, v);
  2596.             Vector_copy_r32(v, fow);
  2597.             Util_t(upp, C1, C2, C3, v);
  2598.             Vector_copy_r32(v, upp);
  2599.             Vector_normalize(fow);
  2600.             Vector_normalize(upp);
  2601.             a = (Rnd() * r * (r32) 2.0) - r;
  2602.             Set_rot(a, fow);
  2603.             Util_t(lef, C1, C2, C3, v);
  2604.             Vector_copy_r32(v, lef);
  2605.             Util_t(upp, C1, C2, C3, v);
  2606.             Vector_copy_r32(v, upp);
  2607.             Vector_normalize(lef);
  2608.             Vector_normalize(upp);
  2609.             break;
  2610.  
  2611.           case 't':
  2612.             if ((fow[_x] == (r32) 0.0) && (fow[_y] == (r32) 0.0))
  2613.                 break;
  2614.             save.tr = tr;
  2615.             if (trope_set)
  2616.                 tr = trope_amount;
  2617.             if (next == '(') {
  2618.                 tr = Get_value(&i);
  2619.                 if (last_recur)
  2620.                     tr *= fraction;
  2621.             }
  2622.             Vector_copy_r32(fow, trope);
  2623.             trope[_x] = -trope[_x];
  2624.             trope[_y] = -trope[_y];
  2625.             trope[_z] = (r32) 0.0;
  2626.             Vector_normalize(trope);
  2627.             r = tr * Scalar_product(fow, trope);
  2628.             Set_rot(-r, lef);
  2629.             Util_t(fow, C1, C2, C3, v);
  2630.             Vector_copy_r32(v, fow);
  2631.             Util_t(upp, C1, C2, C3, v);
  2632.             Vector_copy_r32(v, upp);
  2633.             Vector_normalize(fow);
  2634.             Vector_normalize(upp);
  2635.             tr = save.tr;
  2636.             break;
  2637.  
  2638.           case '$':
  2639.             Vector_min(fow, sky, v);
  2640.             if (Vector_length(v) == (r32) 0.0)
  2641.                 break;
  2642.             Vector_product(fow, sky, lef);
  2643.             Vector_product(fow, lef, upp);
  2644.             if (upp[_z] < (r32) 0.0) {
  2645.                 upp[_x] = -upp[_x];
  2646.                 upp[_y] = -upp[_y];
  2647.                 upp[_z] = -upp[_z];
  2648.                 lef[_x] = -lef[_x];
  2649.                 lef[_y] = -lef[_y];
  2650.                 lef[_z] = -lef[_z];
  2651.             }
  2652.             break;
  2653.  
  2654.           case '&':
  2655.             save.ang = ang;
  2656.             if (next == '(') {
  2657.                 ang = ((r32) 0.017453) * Get_value(&i);
  2658.                 if (last_recur)
  2659.                     ang *= fraction;
  2660.             }
  2661.             Set_rot(ang, lef);
  2662.             Util_t(fow, C1, C2, C3, v);
  2663.             Vector_copy_r32(v, fow);
  2664.             Util_t(upp, C1, C2, C3, v);
  2665.             Vector_copy_r32(v, upp);
  2666.             Vector_normalize(fow);
  2667.             Vector_normalize(upp);
  2668.             ang = save.ang;
  2669.             break;
  2670.  
  2671.           case '^':
  2672.             save.ang = ang;
  2673.             if (next == '(') {
  2674.                 ang = ((r32) 0.017453) * Get_value(&i);
  2675.                 if (last_recur)
  2676.                     ang *= fraction;
  2677.             }
  2678.             Set_rot(-ang, lef);
  2679.             Util_t(fow, C1, C2, C3, v);
  2680.             Vector_copy_r32(v, fow);
  2681.             Util_t(upp, C1, C2, C3, v);
  2682.             Vector_copy_r32(v, upp);
  2683.             Vector_normalize(fow);
  2684.             Vector_normalize(upp);
  2685.             ang = save.ang;
  2686.             break;
  2687.  
  2688.           case '<':
  2689.             save.ang = ang;
  2690.             if (next == '(') {
  2691.                 ang = ((r32) 0.017453) * Get_value(&i);
  2692.                 if (last_recur)
  2693.                     ang *= fraction;
  2694.             }
  2695.             Set_rot(-ang, fow);
  2696.             Util_t(lef, C1, C2, C3, v);
  2697.             Vector_copy_r32(v, lef);
  2698.             Util_t(upp, C1, C2, C3, v);
  2699.             Vector_copy_r32(v, upp);
  2700.             Vector_normalize(lef);
  2701.             Vector_normalize(upp);
  2702.             ang = save.ang;
  2703.             break;
  2704.  
  2705.           case '>':
  2706.             save.ang = ang;
  2707.             if (next == '(') {
  2708.                 ang = ((r32) 0.017453) * Get_value(&i);
  2709.                 if (last_recur)
  2710.                     ang *= fraction;
  2711.             }
  2712.             Set_rot(ang, fow);
  2713.             Util_t(lef, C1, C2, C3, v);
  2714.             Vector_copy_r32(v, lef);
  2715.             Util_t(upp, C1, C2, C3, v);
  2716.             Vector_copy_r32(v, upp);
  2717.             Vector_normalize(lef);
  2718.             Vector_normalize(upp);
  2719.             ang = save.ang;
  2720.             break;
  2721.  
  2722.           case '%':
  2723.             Set_rot(3.141592654, fow);
  2724.             Util_t(lef, C1, C2, C3, v);
  2725.             Vector_copy_r32(v, lef);
  2726.             Util_t(upp, C1, C2, C3, v);
  2727.             Vector_copy_r32(v, upp);
  2728.             Vector_normalize(lef);
  2729.             Vector_normalize(upp);
  2730.             break;
  2731.  
  2732.           case '|':
  2733.             Set_rot(3.141592654, upp);
  2734.             Util_t(fow, C1, C2, C3, v);
  2735.             Vector_copy_r32(v, fow);
  2736.             Util_t(lef, C1, C2, C3, v);
  2737.             Vector_copy_r32(v, lef);
  2738.             Vector_normalize(fow);
  2739.             Vector_normalize(lef);
  2740.             break;
  2741.  
  2742.           case '!':
  2743.             if (next == '(') {
  2744.                 if (last_recur)
  2745.                     thick *= one + fraction * (Get_value(&i) - one);
  2746.                 else
  2747.                     thick *= Get_value(&i);
  2748.             } else {
  2749.                 if (last_recur)
  2750.                     thick *= one + fraction * ((r32) 0.7 - one);
  2751.                 else
  2752.                     thick *= (r32) 0.7;
  2753.             }
  2754.             break;
  2755.  
  2756.           case '?':
  2757.             if (next == '(') {
  2758.                 if (last_recur)
  2759.                     thick *= one + fraction * (Get_value(&i) - one);
  2760.                 else
  2761.                     thick *= Get_value(&i);
  2762.             } else {
  2763.                 if (last_recur)
  2764.                     thick /= one + fraction * ((r32) 0.7 - one);
  2765.                 else
  2766.                     thick /= (r32) 0.7;
  2767.             }
  2768.             break;
  2769.  
  2770.           case ':':
  2771.             if (next == '(') {
  2772.                 if (last_recur)
  2773.                     ang *= one + fraction * (Get_value(&i) - one);
  2774.                 else
  2775.                     ang *= Get_value(&i);
  2776.             } else {
  2777.                 if (last_recur)
  2778.                     ang *= one + fraction * ((r32) 0.9 - one);
  2779.                 else
  2780.                     ang *= (r32) 0.9;
  2781.             }
  2782.             break;
  2783.  
  2784.           case ';':
  2785.             if (next == '(') {
  2786.                 if (last_recur)
  2787.                     ang *= one + fraction * (Get_value(&i) - one);
  2788.                 else
  2789.                     ang *= Get_value(&i);
  2790.             } else {
  2791.                 if (last_recur)
  2792.                     ang /= one + fraction * ((r32) 0.9 - one);
  2793.                 else
  2794.                     ang /= (r32) 0.9;
  2795.             }
  2796.             break;
  2797.  
  2798.           case '\'':
  2799.             if (next == '(') {
  2800.                 r = Get_value(&i);
  2801.                 if (last_recur) {
  2802.                     dis *= one + fraction * (r - one);
  2803.                     dis2 *= one + fraction * (r - one);
  2804.                 } else {
  2805.                     dis *= r;
  2806.                     dis2 *= r;
  2807.                 }
  2808.             } else {
  2809.                 if (last_recur) {
  2810.                     dis *= one + fraction * ((r32) 0.9 - one);
  2811.                     dis2 *= one + fraction * ((r32) 0.9 - one);
  2812.                 } else {
  2813.                     dis *= (r32) 0.9;
  2814.                     dis2 *= (r32) 0.9;
  2815.                 }
  2816.             }
  2817.             break;
  2818.  
  2819.           case '\"':
  2820.             if (next == '(') {
  2821.                 r = Get_value(&i);
  2822.                 if (last_recur) {
  2823.                     dis *= one + fraction * (r - one);
  2824.                     dis2 *= one + fraction * (r - one);
  2825.                 } else {
  2826.                     dis *= r;
  2827.                     dis2 *= r;
  2828.                 }
  2829.             } else {
  2830.                 if (last_recur) {
  2831.                     dis /= one + fraction * ((r32) 0.9 - one);
  2832.                     dis2 /= one + fraction * ((r32) 0.9 - one);
  2833.                 } else {
  2834.                     dis /= (r32) 0.9;
  2835.                     dis2 /= (r32) 0.9;
  2836.                 }
  2837.             }
  2838.             break;
  2839.  
  2840.           case 'Z':
  2841.             save.dis2 = dis2;
  2842.             if (next == '(') {
  2843.                 dis2 = Get_value(&i);
  2844.                 if (last_recur)
  2845.                     dis2 *= fraction;
  2846.             }
  2847.             Vector_plus_fac(pos, fow, dis2, end);
  2848.             if (user_form)
  2849.                 Define_form(pos, end, upp, col);
  2850.             else if (closed_form)
  2851.                 Define_closed(pos, end, upp, col);
  2852.             else
  2853.                 Define_block(pos, end, upp, col);
  2854.             Vector_copy_r32(end, pos);
  2855.             dis2 = save.dis2;
  2856.             break;
  2857.  
  2858.           case 'F':
  2859.             save.dis = dis;
  2860.             if (next == '(') {
  2861.                 dis = Get_value(&i);
  2862.                 if (last_recur)
  2863.                     dis *= fraction;
  2864.             }
  2865.             Vector_plus_fac(pos, fow, dis, end);
  2866.             if (user_form)
  2867.                 Define_form(pos, end, upp, col);
  2868.             else if (closed_form)
  2869.                 Define_closed(pos, end, upp, col);
  2870.             else
  2871.                 Define_block(pos, end, upp, col);
  2872.             Vector_copy_r32(end, pos);
  2873.             dis = save.dis;
  2874.             break;
  2875.  
  2876.           case '[':
  2877.             if (scount > max_stack)
  2878.                 User_error("Ran out of stack");
  2879.             Vector_copy_r32(pos, stack[scount].pos);
  2880.             Vector_copy_r32(fow, stack[scount].fow);
  2881.             Vector_copy_r32(lef, stack[scount].lef);
  2882.             Vector_copy_r32(upp, stack[scount].upp);
  2883.             stack[scount].col = col;
  2884.             stack[scount].dis = dis;
  2885.             stack[scount].dis2 = dis2;
  2886.             stack[scount].ang = ang;
  2887.             stack[scount].thick = thick;
  2888.             stack[scount].tr = tr;
  2889.             if (closed_form) {
  2890.                 Vector_copy_r32(last, stack[scount].last);
  2891.                 stack[scount].last_col = last_col;
  2892.                 for (j = 1; j <= 8; j++)
  2893.                     Vector_copy_r32(last_v[j], stack[scount].last_v[j]);
  2894.             }
  2895.             scount++;
  2896.             break;
  2897.  
  2898.           case ']':
  2899.             scount--;
  2900.             Vector_copy_r32(stack[scount].pos, pos);
  2901.             Vector_copy_r32(stack[scount].fow, fow);
  2902.             Vector_copy_r32(stack[scount].lef, lef);
  2903.             Vector_copy_r32(stack[scount].upp, upp);
  2904.             col = stack[scount].col;
  2905.             dis = stack[scount].dis;
  2906.             dis2 = stack[scount].dis2;
  2907.             ang = stack[scount].ang;
  2908.             thick = stack[scount].thick;
  2909.             tr = stack[scount].tr;
  2910.             if (closed_form) {
  2911.                 Vector_copy_r32(stack[scount].last, last);
  2912.                 last_col = stack[scount].last_col;
  2913.                 for (j = 1; j <= 8; j++)
  2914.                     Vector_copy_r32(stack[scount].last_v[j], last_v[j]);
  2915.             }
  2916.             break;
  2917.  
  2918.           case '{':
  2919.             if (poly_on) {
  2920.                 pstack[pscount].count = vcount;
  2921.                 pstack[pscount].ver = (vector *) malloc(vcount * 12L);
  2922.                 if (pstack[pscount].ver == NULL)
  2923.                     User_error("Ran out of memory");
  2924.                 Vector_copy_max_r32(vcount, ver, pstack[pscount].ver);
  2925.                 pscount++;
  2926.                 if (pscount > max_stack)
  2927.                     User_error("Ran out of stack");
  2928.             }
  2929.             poly_on = TRUE;
  2930.             vcount = (s16) 1;
  2931.             pcount = (s16) 1;
  2932.             Vector_copy_r32(pos, ver[vcount++]);
  2933.             break;
  2934.  
  2935.           case 'f':
  2936.             save.dis = dis;
  2937.             if (next == '(') {
  2938.                 dis = Get_value(&i);
  2939.                 if (last_recur)
  2940.                     dis *= fraction;
  2941.             }
  2942.             Vector_plus_fac(pos, fow, dis, pos);
  2943.             if (poly_on)
  2944.                 Vector_copy_r32(pos, ver[vcount++]);
  2945.             dis = save.dis;
  2946.             break;
  2947.  
  2948.           case '.':
  2949.             if (poly_on)
  2950.                 Vector_copy_r32(pos, ver[vcount++]);
  2951.             break;
  2952.  
  2953.           case 'g':
  2954.             save.dis = dis;
  2955.             if (next == '(') {
  2956.                 dis = Get_value(&i);
  2957.                 if (last_recur)
  2958.                     dis *= fraction;
  2959.             }
  2960.             Vector_plus_fac(pos, fow, dis, pos);
  2961.             dis = save.dis;
  2962.             break;
  2963.  
  2964.           case 'z':
  2965.             save.dis2 = dis2;
  2966.             if (next == '(') {
  2967.                 dis2 = Get_value(&i);
  2968.                 if (last_recur)
  2969.                     dis2 *= fraction;
  2970.             }
  2971.             Vector_plus_fac(pos, fow, dis2, pos);
  2972.             if (poly_on)
  2973.                 Vector_copy_r32(pos, ver[vcount++]);
  2974.             dis2 = save.dis2;
  2975.             break;
  2976.  
  2977.           case '}':
  2978.             if (vcount > (s16) 3) {
  2979.                 for (j = 1; j < vcount - 2; j++) {
  2980.                     poly_store[pcount][0] = 1;
  2981.                     poly_store[pcount][1] = j + 1;
  2982.                     poly_store[pcount][2] = j + 2;
  2983.                     poly_store[pcount++][3] = j + 2;
  2984.                 }
  2985.                 Save_object(vcount - 1, pcount - 1, col);
  2986.             }
  2987.             poly_on = FALSE;
  2988.             if (pscount > 0) {
  2989.                 pscount--;
  2990.                 Vector_copy_max_r32(pstack[pscount].count, pstack[pscount].ver, ver);
  2991.                 vcount = pstack[pscount].count;
  2992.                 poly_on = TRUE;
  2993.             }
  2994.             break;
  2995.  
  2996.           case 'c':
  2997.             if (next == '(') {
  2998.                 col = (s16) Get_value(&i);
  2999.             } else {
  3000.                 col++;
  3001.             }
  3002.             break;
  3003.         }
  3004.     };
  3005.  
  3006.     Process_end2();
  3007. }
  3008.  
  3009.  
  3010. /* Lparser main ----------------------------------------------------------- */
  3011.  
  3012.  
  3013. static void
  3014. Help(void)
  3015. {
  3016.     char                    s[max_file];
  3017.  
  3018.     Get_comline_progname(s);
  3019.     Message("%s [options] ls-filename\n\n", s);
  3020.  
  3021.     Message("%s \tnone      (default) output Lviewer VOL file\n", "vol");
  3022.     Message("%s \t-v        output POV object file\n", "pov");
  3023.     Message("%s \t-b        output POV blob file\n", "pov");
  3024.     Message("%s \t-B        output multiple POV blob files\n", "pov");
  3025.     Message("%s \t-c        output inc files instead of pov files\n", "pov");
  3026.     Message("%s \t-d        output polyface meshes DXF file\n", "dxf");
  3027.     Message("%s \t-3        output 3dfaces DXF file\n", "dxf");
  3028.     Message("%s \t-R        output triangles in RAW file\n", "raw");
  3029.     Message("%s \t-O        output Blob Sculptor BLB file\n", "blb");
  3030.     Message("%s \t-V        output VRML world file\n", "wrl");
  3031.  
  3032.     Message("%s \t-X [name] use name.vol as base element\n", "base");
  3033.     Message("%s \t-i        link base elements together\n", "base");
  3034.  
  3035.     Message("%s \t-S [num]  set string size to num Kbytes\n", "set");
  3036.     Message("%s \t-t [num]  set minimum thickness\n", "set");
  3037.     Message("%s \t-r [num]  overrule recursion depth\n", "set");
  3038.     Message("%s \t-a [num]  overrule angle\n", "set");
  3039.  
  3040.     Message("%s \t-u [num]  mutate [num] times\n", "ls");
  3041.     Message("%s \t-l        show final L-string\n", "ls");
  3042.     Message("%s \t-g        add ground plane\n", "ls");
  3043.     Message("%s \t-L [num]  set amount for ~ command\n", "ls");
  3044.     Message("%s \t-P [num]  set amount for t command\n", "ls");
  3045.  
  3046.     Message("%s \t-p [num]  limit polygons to [num]\n", "limit");
  3047. }
  3048.  
  3049.  
  3050. void
  3051. main(int argc, char *argv[])
  3052. {
  3053.     char                    temp[max_file];
  3054.     boolean                 found;
  3055.     s16                     tim, i;
  3056.  
  3057.  /* Store the pointers to the comline */
  3058.     s_argc = argc;
  3059.     s_argv = argv;
  3060.  
  3061.  /* Display header and help file if needed */
  3062.     Message("%s\n", min_bar);
  3063.     Message("%s v%s (%s)\n", "L-System Parser/Mutator", "5.0", __DATE__);
  3064.     Message("%s\n", min_bar);
  3065.  
  3066.     if (argc < 2) {
  3067.         Help();
  3068.         User_error("Need arguments\n");
  3069.     };
  3070.  
  3071.  /* Set the option string */
  3072.     strcpy(opts, "VP:OhL:S:iecBbRd3vX:p:t:u:r:a:gl");
  3073.  
  3074.  /* Init files */
  3075.     Init_file_buf(0);
  3076.     Init_file_buf(1);
  3077.     Init_file_buf(2);
  3078.  
  3079.  /* Check for all the comline options */
  3080.     Get_comline_opt("t", &found, temp);    /* set minimum thickness */
  3081.     if (found)
  3082.         sscanf(temp, "%f", &min_thick);
  3083.  
  3084.     Get_comline_opt("p", &found, temp);    /* limit total generated polygons */
  3085.     if (found)
  3086.         sscanf(temp, "%ld", &poly_limit);
  3087.  
  3088.     Get_comline_opt("L", &rand_set, temp); /* set random amount */
  3089.     if (rand_set) {
  3090.         sscanf(temp, "%f", &rand_amount);
  3091.         srand(0);                          /* when using changing amounts of
  3092.                                             * randomness for animations we want
  3093.                                             * the seed to be the same so we set
  3094.                                             * it here */
  3095.     } else {
  3096.         srand(time(NULL));
  3097.     };
  3098.  
  3099.     Get_comline_opt("P", &trope_set, temp);/* set amount of trope */
  3100.     if (trope_set) {
  3101.         sscanf(temp, "%f", &trope_amount);
  3102.         srand(0);                          /* same for trope animations */
  3103.     };
  3104.  
  3105.     Get_comline_opt("S", &found, temp);    /* set maximum production string
  3106.                                             * size in kbytes */
  3107.     if (found) {
  3108.         sscanf(temp, "%ld", &max_string);
  3109.         max_string *= 1024L;               /* we will need two string of this
  3110.                                             * size ! */
  3111.     } else {
  3112.         max_string = 2L * 1024L * 1024L;   /* default is 2 mbytes */
  3113.     };
  3114.  
  3115.     Get_comline_opt("X", &user_form, x_name);   /* use a vol file as user shape */
  3116.     Get_comline_opt("i", &closed_form, temp);   /* create closed connected
  3117.                                                  * cylinders */
  3118.     Get_comline_opt("d", &dxf1, temp);     /* create a dxf file with inserts */
  3119.     Get_comline_opt("3", &dxf2, temp);     /* create a dxf with only polygons */
  3120.     Get_comline_opt("R", &dxf3, temp);     /* create a RAW triangle file */
  3121.     Get_comline_opt("V", &vrml, temp);     /* create a WRL VRML v1.0 file */
  3122.     Get_comline_opt("B", &pov_form3, temp);/* create multiple povray blob files
  3123.                                             * for multi colord blobs */
  3124.  
  3125.     Get_comline_opt("O", &blb_form, temp); /* create a blb blob file */
  3126.     Get_comline_opt("b", &pov_form2, temp);/* create a povray blob file */
  3127.     Get_comline_opt("v", &pov_form, temp); /* create a povray file */
  3128.     Get_comline_opt("c", &inc_out, temp);  /* create a povray inc file */
  3129.  
  3130.  /*
  3131.   * In these cases an user defined form is used. In the other cases a simple
  3132.   * block or connected cylinder shape will be used.
  3133.   */
  3134.     if (pov_form || pov_form2 || pov_form3 || blb_form)
  3135.         user_form = TRUE;
  3136.  
  3137.  /* Read ls file and setup rules */
  3138.     L_init();
  3139.  
  3140.  /* Execute mutations */
  3141.     Get_comline_opt("u", &found, temp);
  3142.     if (found) {
  3143.         sscanf(temp, "%hd", &tim);
  3144.         Message("Mutating       : ..");
  3145.         for (i = 0; i < tim; i++) {
  3146.             Message("\b\b%-2d", i + 1);
  3147.             L_mutate();                    /* perform mutations on stored rule
  3148.                                             * set */
  3149.         }
  3150.         Message("\n");
  3151.         L_save();                          /* save the mutated ls file */
  3152.     };
  3153.  
  3154.  /* Create L-system production string */
  3155.     L_system();
  3156.  
  3157.  /* Parse production string and create geometry */
  3158.     L_draw();
  3159.  
  3160.  /* Add groundplane */
  3161.     Get_comline_opt("g", &found, temp);
  3162.     if (found)
  3163.         Ground_plane();
  3164.  
  3165.     Close_datafile();
  3166.  
  3167.     Message("\n");
  3168. }
  3169.  
  3170.  
  3171. /* -------------------------------------------------------------------------
  3172.    End of file.
  3173.    -------------------------------------------------------------------------
  3174. */
  3175.